]> gitweb.ps.run Git - autorec/blob - src/mongoose.c
ws connect works
[autorec] / src / mongoose.c
1 // Copyright (c) 2004-2013 Sergey Lyubka
2 // Copyright (c) 2013-2021 Cesanta Software Limited
3 // All rights reserved
4 //
5 // This software is dual-licensed: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License version 2 as
7 // published by the Free Software Foundation. For the terms of this
8 // license, see http://www.gnu.org/licenses/
9 //
10 // You are free to use this software under the terms of the GNU General
11 // Public License, but WITHOUT ANY WARRANTY; without even the implied
12 // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU General Public License for more details.
14 //
15 // Alternatively, you can license this software under a commercial
16 // license, as set out in https://www.mongoose.ws/licensing/
17
18 #include "mongoose.h"
19
20 #ifdef MG_ENABLE_LINES
21 #line 1 "src/base64.c"
22 #endif
23
24 #include <string.h>
25
26 static int mg_b64idx(int c) {
27   if (c < 26) {
28     return c + 'A';
29   } else if (c < 52) {
30     return c - 26 + 'a';
31   } else if (c < 62) {
32     return c - 52 + '0';
33   } else {
34     return c == 62 ? '+' : '/';
35   }
36 }
37
38 static int mg_b64rev(int c) {
39   if (c >= 'A' && c <= 'Z') {
40     return c - 'A';
41   } else if (c >= 'a' && c <= 'z') {
42     return c + 26 - 'a';
43   } else if (c >= '0' && c <= '9') {
44     return c + 52 - '0';
45   } else if (c == '+') {
46     return 62;
47   } else if (c == '/') {
48     return 63;
49   } else if (c == '=') {
50     return 64;
51   } else {
52     return -1;
53   }
54 }
55
56 int mg_base64_update(unsigned char ch, char *to, int n) {
57   int rem = (n & 3) % 3;
58   if (rem == 0) {
59     to[n] = (char) mg_b64idx(ch >> 2);
60     to[++n] = (char) ((ch & 3) << 4);
61   } else if (rem == 1) {
62     to[n] = (char) mg_b64idx(to[n] | (ch >> 4));
63     to[++n] = (char) ((ch & 15) << 2);
64   } else {
65     to[n] = (char) mg_b64idx(to[n] | (ch >> 6));
66     to[++n] = (char) mg_b64idx(ch & 63);
67     n++;
68   }
69   return n;
70 }
71
72 int mg_base64_final(char *to, int n) {
73   int saved = n;
74   // printf("---[%.*s]\n", n, to);
75   if (n & 3) n = mg_base64_update(0, to, n);
76   if ((saved & 3) == 2) n--;
77   // printf("    %d[%.*s]\n", n, n, to);
78   while (n & 3) to[n++] = '=';
79   to[n] = '\0';
80   return n;
81 }
82
83 int mg_base64_encode(const unsigned char *p, int n, char *to) {
84   int i, len = 0;
85   for (i = 0; i < n; i++) len = mg_base64_update(p[i], to, len);
86   len = mg_base64_final(to, len);
87   return len;
88 }
89
90 int mg_base64_decode(const char *src, int n, char *dst) {
91   const char *end = src + n;
92   int len = 0;
93   while (src + 3 < end) {
94     int a = mg_b64rev(src[0]), b = mg_b64rev(src[1]), c = mg_b64rev(src[2]),
95         d = mg_b64rev(src[3]);
96     if (a == 64 || a < 0 || b == 64 || b < 0 || c < 0 || d < 0) return 0;
97     dst[len++] = (char) ((a << 2) | (b >> 4));
98     if (src[2] != '=') {
99       dst[len++] = (char) ((b << 4) | (c >> 2));
100       if (src[3] != '=') dst[len++] = (char) ((c << 6) | d);
101     }
102     src += 4;
103   }
104   dst[len] = '\0';
105   return len;
106 }
107
108 #ifdef MG_ENABLE_LINES
109 #line 1 "src/dns.c"
110 #endif
111
112
113
114
115
116
117 struct dns_data {
118   struct dns_data *next;
119   struct mg_connection *c;
120   unsigned long expire;
121   uint16_t txnid;
122 };
123
124 static struct dns_data *s_reqs;  // Active DNS requests
125
126 static void mg_sendnsreq(struct mg_connection *, struct mg_str *, int,
127                          struct mg_dns *, bool);
128
129 static void mg_dns_free(struct dns_data *d) {
130   LIST_DELETE(struct dns_data, &s_reqs, d);
131   free(d);
132 }
133
134 void mg_resolve_cancel(struct mg_connection *c) {
135   struct dns_data *tmp, *d;
136   for (d = s_reqs; d != NULL; d = tmp) {
137     tmp = d->next;
138     if (d->c == c) mg_dns_free(d);
139   }
140 }
141
142 static size_t mg_dns_parse_name_depth(const uint8_t *s, size_t len, size_t ofs,
143                                       char *to, size_t tolen, int depth) {
144   size_t i = 0, j = 0;
145   if (tolen > 0) to[0] = '\0';
146   if (depth > 5) return 0;
147   while (ofs + i + 1 < len) {
148     size_t n = s[ofs + i];
149     if (n == 0) {
150       i++;
151       break;
152     }
153     if (n & 0xc0) {
154       size_t ptr = (((n & 0x3f) << 8) | s[ofs + i + 1]);  // 12 is hdr len
155       if (ptr + 1 < len && (s[ptr] & 0xc0) == 0 &&
156           mg_dns_parse_name_depth(s, len, ptr, to, tolen, depth + 1) == 0)
157         return 0;
158       i += 2;
159       break;
160     }
161     if (ofs + i + n + 1 >= len) return 0;
162     if (j > 0) {
163       if (j < tolen) to[j] = '.';
164       j++;
165     }
166     if (j + n < tolen) memcpy(&to[j], &s[ofs + i + 1], n);
167     j += n;
168     i += n + 1;
169     if (j < tolen) to[j] = '\0';  // Zero-terminate this chunk
170   }
171   if (tolen > 0) to[tolen - 1] = '\0';  // Make sure make sure it is nul-term
172   return i;
173 }
174
175 static size_t mg_dns_parse_name(const uint8_t *s, size_t n, size_t ofs,
176                                 char *dst, size_t dstlen) {
177   return mg_dns_parse_name_depth(s, n, ofs, dst, dstlen, 0);
178 }
179
180 size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
181                        bool is_question, struct mg_dns_rr *rr) {
182   const uint8_t *s = buf + ofs, *e = &buf[len];
183
184   memset(rr, 0, sizeof(*rr));
185   if (len < sizeof(struct mg_dns_header)) return 0;  // Too small
186   if (len > 512) return 0;  //  Too large, we don't expect that
187   if (s >= e) return 0;     //  Overflow
188
189   if ((rr->nlen = (uint16_t) mg_dns_parse_name(buf, len, ofs, NULL, 0)) == 0)
190     return 0;
191   s += rr->nlen + 4;
192   if (s > e) return 0;
193   rr->atype = (uint16_t) (((uint16_t) s[-4] << 8) | s[-3]);
194   rr->aclass = (uint16_t) (((uint16_t) s[-2] << 8) | s[-1]);
195   if (is_question) return (size_t) (rr->nlen + 4);
196
197   s += 6;
198   if (s > e) return 0;
199   rr->alen = (uint16_t) (((uint16_t) s[-2] << 8) | s[-1]);
200   if (s + rr->alen > e) return 0;
201   return (size_t) (rr->nlen + rr->alen + 10);
202 }
203
204 bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
205   const struct mg_dns_header *h = (struct mg_dns_header *) buf;
206   struct mg_dns_rr rr;
207   size_t i, n, ofs = sizeof(*h);
208   memset(dm, 0, sizeof(*dm));
209
210   if (len < sizeof(*h)) return 0;                // Too small, headers dont fit
211   if (mg_ntohs(h->num_questions) > 1) return 0;  // Sanity
212   if (mg_ntohs(h->num_answers) > 10) return 0;   // Sanity
213   dm->txnid = mg_ntohs(h->txnid);
214
215   for (i = 0; i < mg_ntohs(h->num_questions); i++) {
216     if ((n = mg_dns_parse_rr(buf, len, ofs, true, &rr)) == 0) return false;
217     // LOG(LL_INFO, ("Q %zu %zu", ofs, n));
218     ofs += n;
219   }
220   for (i = 0; i < mg_ntohs(h->num_answers); i++) {
221     // LOG(LL_INFO, ("A -- %zu %zu %s", ofs, n, dm->name));
222     if ((n = mg_dns_parse_rr(buf, len, ofs, false, &rr)) == 0) return false;
223     mg_dns_parse_name(buf, len, ofs, dm->name, sizeof(dm->name));
224     ofs += n;
225
226     if (rr.alen == 4 && rr.atype == 1 && rr.aclass == 1) {
227       dm->addr.is_ip6 = false;
228       memcpy(&dm->addr.ip, &buf[ofs - 4], 4);
229       dm->resolved = true;
230       break;  // Return success
231     } else if (rr.alen == 16 && rr.atype == 28 && rr.aclass == 1) {
232       dm->addr.is_ip6 = true;
233       memcpy(&dm->addr.ip6, &buf[ofs - 16], 16);
234       dm->resolved = true;
235       break;  // Return success
236     }
237   }
238   return true;
239 }
240
241 static void dns_cb(struct mg_connection *c, int ev, void *ev_data,
242                    void *fn_data) {
243   struct dns_data *d, *tmp;
244   if (ev == MG_EV_POLL) {
245     unsigned long now = *(unsigned long *) ev_data;
246     for (d = s_reqs; d != NULL; d = tmp) {
247       tmp = d->next;
248       // LOG(LL_DEBUG, ("%lu %lu dns poll", d->expire, now));
249       if (now > d->expire) mg_error(d->c, "DNS timeout");
250     }
251   } else if (ev == MG_EV_READ) {
252     struct mg_dns_message dm;
253     int resolved = 0;
254     if (mg_dns_parse(c->recv.buf, c->recv.len, &dm) == false) {
255       char *s = mg_hexdump(c->recv.buf, c->recv.len);
256       LOG(LL_ERROR, ("Unexpected DNS response:\n%s\n", s));
257       free(s);
258     } else {
259       LOG(LL_VERBOSE_DEBUG, ("%s %d", dm.name, dm.resolved));
260       for (d = s_reqs; d != NULL; d = tmp) {
261         tmp = d->next;
262         // LOG(LL_INFO, ("d %p %hu %hu", d, d->txnid, dm.txnid));
263         if (dm.txnid != d->txnid) continue;
264         if (d->c->is_resolving) {
265           d->c->is_resolving = 0;
266           if (dm.resolved) {
267 #if MG_ENABLE_LOG
268             char buf[100];
269 #endif
270             dm.addr.port = d->c->peer.port;  // Save port
271             d->c->peer = dm.addr;            // Copy resolved address
272             LOG(LL_DEBUG, ("%lu %s resolved to %s", d->c->id, dm.name,
273                            mg_ntoa(&d->c->peer, buf, sizeof(buf))));
274             mg_connect_resolved(d->c);
275 #if MG_ENABLE_IPV6
276           } else if (dm.addr.is_ip6 == false && dm.name[0] != '\0') {
277             struct mg_str x = mg_str(dm.name);
278             mg_sendnsreq(d->c, &x, c->mgr->dnstimeout, &c->mgr->dns6, true);
279 #endif
280           } else {
281             mg_error(d->c, "%s DNS lookup failed", dm.name);
282           }
283         } else {
284           LOG(LL_ERROR, ("%lu already resolved", d->c->id));
285         }
286         mg_dns_free(d);
287         resolved = 1;
288       }
289     }
290     if (!resolved) LOG(LL_ERROR, ("stray DNS reply"));
291     c->recv.len = 0;
292   } else if (ev == MG_EV_CLOSE) {
293     for (d = s_reqs; d != NULL; d = tmp) {
294       tmp = d->next;
295       mg_dns_free(d);
296     }
297   }
298   (void) fn_data;
299 }
300
301 static void mg_dns_send(struct mg_connection *c, const struct mg_str *name,
302                         uint16_t txnid, bool ipv6) {
303   struct {
304     struct mg_dns_header header;
305     uint8_t data[256];
306   } pkt;
307   size_t i, n;
308   memset(&pkt, 0, sizeof(pkt));
309   pkt.header.txnid = mg_htons(txnid);
310   pkt.header.flags = mg_htons(0x100);
311   pkt.header.num_questions = mg_htons(1);
312   for (i = n = 0; i < sizeof(pkt.data) - 5; i++) {
313     if (name->ptr[i] == '.' || i >= name->len) {
314       pkt.data[n] = (uint8_t) (i - n);
315       memcpy(&pkt.data[n + 1], name->ptr + n, i - n);
316       n = i + 1;
317     }
318     if (i >= name->len) break;
319   }
320   memcpy(&pkt.data[n], "\x00\x00\x01\x00\x01", 5);  // A query
321   n += 5;
322   if (ipv6) pkt.data[n - 3] = 0x1c;  // AAAA query
323   // memcpy(&pkt.data[n], "\xc0\x0c\x00\x1c\x00\x01", 6);  // AAAA query
324   // n += 6;
325   mg_send(c, &pkt, sizeof(pkt.header) + n);
326 #if 0
327   // Immediately after A query, send AAAA query. Whatever reply comes first,
328   // we'll use it. Note: we cannot send two queries in a single packet.
329   // https://stackoverflow.com/questions/4082081/requesting-a-and-aaaa-records-in-single-dns-query
330   pkt.data[n - 3] = 0x1c;  // AAAA query
331   mg_send(c, &pkt, sizeof(pkt.header) + n);
332 #endif
333 }
334
335 static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
336                          struct mg_dns *dnsc, bool ipv6) {
337   struct dns_data *d = NULL;
338   if (dnsc->url == NULL) {
339     mg_error(c, "DNS server URL is NULL. Call mg_mgr_init()");
340   } else if (dnsc->c == NULL) {
341     dnsc->c = mg_connect(c->mgr, dnsc->url, NULL, NULL);
342     if (dnsc->c != NULL) {
343       dnsc->c->pfn = dns_cb;
344       snprintf(dnsc->c->label, sizeof(dnsc->c->label), "%s", "DNS");
345       // dnsc->c->is_hexdumping = 1;
346     }
347   }
348   if (dnsc->c == NULL) {
349     mg_error(c, "resolver");
350   } else if ((d = (struct dns_data *) calloc(1, sizeof(*d))) == NULL) {
351     mg_error(c, "resolve OOM");
352   } else {
353 #if MG_ENABLE_LOG
354     char buf[100];
355 #endif
356     d->txnid = s_reqs ? (uint16_t) (s_reqs->txnid + 1) : 1;
357     d->next = s_reqs;
358     s_reqs = d;
359     d->expire = mg_millis() + (unsigned long) ms;
360     d->c = c;
361     c->is_resolving = 1;
362     LOG(LL_VERBOSE_DEBUG,
363         ("%lu resolving %.*s @ %s, txnid %hu", c->id, (int) name->len,
364          name->ptr, mg_ntoa(&dnsc->c->peer, buf, sizeof(buf)), d->txnid));
365     mg_dns_send(dnsc->c, name, d->txnid, ipv6);
366   }
367 }
368
369 void mg_resolve(struct mg_connection *c, struct mg_str *name, int ms) {
370   if (mg_aton(*name, &c->peer)) {
371     // name is an IP address, do not fire name resolution
372     mg_connect_resolved(c);
373   } else {
374     // name is not an IP, send DNS resolution request
375     mg_sendnsreq(c, name, ms, &c->mgr->dns4, false);
376   }
377 }
378
379 #ifdef MG_ENABLE_LINES
380 #line 1 "src/event.c"
381 #endif
382
383
384
385
386
387 void mg_call(struct mg_connection *c, int ev, void *ev_data) {
388   // Run user-defined handler first, in order to give it an ability
389   // to intercept processing (e.g. clean input buffer) before the
390   // protocol handler kicks in
391   if (c->fn != NULL) c->fn(c, ev, ev_data, c->fn_data);
392   if (c->pfn != NULL) c->pfn(c, ev, ev_data, c->pfn_data);
393 }
394
395 void mg_error(struct mg_connection *c, const char *fmt, ...) {
396   char mem[256], *buf = mem;
397   va_list ap;
398   va_start(ap, fmt);
399   mg_vasprintf(&buf, sizeof(mem), fmt, ap);
400   va_end(ap);
401   LOG(LL_ERROR, ("%lu %s", c->id, buf));
402   c->is_closing = 1;             // Set is_closing before sending MG_EV_CALL
403   mg_call(c, MG_EV_ERROR, buf);  // Let user handler to override it
404   if (buf != mem) free(buf);
405 }
406
407 #ifdef MG_ENABLE_LINES
408 #line 1 "src/fs_packed.c"
409 #endif
410
411
412 struct packed_file {
413   const char *data;
414   size_t size;
415   size_t pos;
416 };
417
418 const char *mg_unpack(const char *path, size_t *size, time_t *mtime);
419 const char *mg_unlist(size_t no);
420 #if MG_ENABLE_PACKED_FS
421 #else
422 const char *mg_unpack(const char *path, size_t *size, time_t *mtime) {
423   (void) path, (void) size, (void) mtime;
424   return NULL;
425 }
426 const char *mg_unlist(size_t no) {
427   (void) no;
428   return NULL;
429 }
430 #endif
431
432 static int is_dir_prefix(const char *prefix, size_t n, const char *path) {
433   return n < strlen(path) && memcmp(prefix, path, n) == 0 && path[n] == '/';
434   //(n == 0 || path[n] == MG_DIRSEP);
435 }
436
437 static int packed_stat(const char *path, size_t *size, time_t *mtime) {
438   const char *p;
439   size_t i, n = strlen(path);
440   if (mg_unpack(path, size, mtime)) return MG_FS_READ;  // Regular file
441   // Scan all files. If `path` is a dir prefix for any of them, it's a dir
442   for (i = 0; (p = mg_unlist(i)) != NULL; i++) {
443     if (is_dir_prefix(path, n, p)) return MG_FS_DIR;
444   }
445   return 0;
446 }
447
448 static void packed_list(const char *dir, void (*fn)(const char *, void *),
449                         void *userdata) {
450   char buf[256], tmp[sizeof(buf)];
451   const char *path, *begin, *end;
452   size_t i, n = strlen(dir);
453   tmp[0] = '\0';  // Previously listed entry
454   for (i = 0; (path = mg_unlist(i)) != NULL; i++) {
455     if (!is_dir_prefix(dir, n, path)) continue;
456     begin = &path[n + 1];
457     end = strchr(begin, '/');
458     if (end == NULL) end = begin + strlen(begin);
459     snprintf(buf, sizeof(buf), "%.*s", (int) (end - begin), begin);
460     buf[sizeof(buf) - 1] = '\0';
461     // If this entry has been already listed, skip
462     // NOTE: we're assuming that file list is sorted alphabetically
463     if (strcmp(buf, tmp) == 0) continue;
464     fn(buf, userdata);  // Not yet listed, call user function
465     strcpy(tmp, buf);   // And save this entry as listed
466   }
467 }
468
469 static struct mg_fd *packed_open(const char *path, int flags) {
470   size_t size = 0;
471   const char *data = mg_unpack(path, &size, NULL);
472   struct packed_file *fp = NULL;
473   struct mg_fd *fd = NULL;
474   if (data == NULL) return NULL;
475   if (flags & MG_FS_WRITE) return NULL;
476   fp = (struct packed_file *) calloc(1, sizeof(*fp));
477   fd = (struct mg_fd *) calloc(1, sizeof(*fd));
478   fp->size = size;
479   fp->data = data;
480   fd->fd = fp;
481   fd->fs = &mg_fs_packed;
482   return fd;
483 }
484
485 static void packed_close(struct mg_fd *fd) {
486   if (fd) free(fd->fd), free(fd);
487 }
488
489 static size_t packed_read(void *fd, void *buf, size_t len) {
490   struct packed_file *fp = (struct packed_file *) fd;
491   if (fp->pos + len > fp->size) len = fp->size - fp->pos;
492   memcpy(buf, &fp->data[fp->pos], len);
493   fp->pos += len;
494   return len;
495 }
496
497 static size_t packed_write(void *fd, const void *buf, size_t len) {
498   (void) fd, (void) buf, (void) len;
499   return 0;
500 }
501
502 static size_t packed_seek(void *fd, size_t offset) {
503   struct packed_file *fp = (struct packed_file *) fd;
504   fp->pos = offset;
505   if (fp->pos > fp->size) fp->pos = fp->size;
506   return fp->pos;
507 }
508
509 struct mg_fs mg_fs_packed = {packed_stat,  packed_list, packed_open,
510                              packed_close, packed_read, packed_write,
511                              packed_seek};
512
513 #ifdef MG_ENABLE_LINES
514 #line 1 "src/fs_posix.c"
515 #endif
516
517
518 #if defined(FOPEN_MAX)
519 static int p_stat(const char *path, size_t *size, time_t *mtime) {
520 #ifdef _WIN32
521   struct _stati64 st;
522   wchar_t tmp[PATH_MAX];
523   MultiByteToWideChar(CP_UTF8, 0, path, -1, tmp, sizeof(tmp) / sizeof(tmp[0]));
524   if (_wstati64(tmp, &st) != 0) return 0;
525 #else
526   struct stat st;
527   if (stat(path, &st) != 0) return 0;
528 #endif
529   if (size) *size = (size_t) st.st_size;
530   if (mtime) *mtime = st.st_mtime;
531   return MG_FS_READ | MG_FS_WRITE | (S_ISDIR(st.st_mode) ? MG_FS_DIR : 0);
532 }
533
534 #ifdef _WIN32
535 struct dirent {
536   char d_name[MAX_PATH];
537 };
538
539 typedef struct win32_dir {
540   HANDLE handle;
541   WIN32_FIND_DATAW info;
542   struct dirent result;
543 } DIR;
544
545 int gettimeofday(struct timeval *tv, void *tz) {
546   FILETIME ft;
547   unsigned __int64 tmpres = 0;
548
549   if (tv != NULL) {
550     GetSystemTimeAsFileTime(&ft);
551     tmpres |= ft.dwHighDateTime;
552     tmpres <<= 32;
553     tmpres |= ft.dwLowDateTime;
554     tmpres /= 10;  // convert into microseconds
555     tmpres -= (int64_t) 11644473600000000;
556     tv->tv_sec = (long) (tmpres / 1000000UL);
557     tv->tv_usec = (long) (tmpres % 1000000UL);
558   }
559   (void) tz;
560   return 0;
561 }
562
563 static int to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len) {
564   int ret;
565   char buf[MAX_PATH * 2], buf2[MAX_PATH * 2], *p;
566   strncpy(buf, path, sizeof(buf));
567   buf[sizeof(buf) - 1] = '\0';
568   // Trim trailing slashes. Leave backslash for paths like "X:\"
569   p = buf + strlen(buf) - 1;
570   while (p > buf && p[-1] != ':' && (p[0] == '\\' || p[0] == '/')) *p-- = '\0';
571   memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
572   ret = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len);
573   // Convert back to Unicode. If doubly-converted string does not match the
574   // original, something is fishy, reject.
575   WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2),
576                       NULL, NULL);
577   if (strcmp(buf, buf2) != 0) {
578     wbuf[0] = L'\0';
579     ret = 0;
580   }
581   return ret;
582 }
583
584 DIR *opendir(const char *name) {
585   DIR *d = NULL;
586   wchar_t wpath[MAX_PATH];
587   DWORD attrs;
588
589   if (name == NULL) {
590     SetLastError(ERROR_BAD_ARGUMENTS);
591   } else if ((d = (DIR *) calloc(1, sizeof(*d))) == NULL) {
592     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
593   } else {
594     to_wchar(name, wpath, sizeof(wpath) / sizeof(wpath[0]));
595     attrs = GetFileAttributesW(wpath);
596     if (attrs != 0Xffffffff && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
597       (void) wcscat(wpath, L"\\*");
598       d->handle = FindFirstFileW(wpath, &d->info);
599       d->result.d_name[0] = '\0';
600     } else {
601       free(d);
602       d = NULL;
603     }
604   }
605   return d;
606 }
607
608 int closedir(DIR *d) {
609   int result = 0;
610   if (d != NULL) {
611     if (d->handle != INVALID_HANDLE_VALUE)
612       result = FindClose(d->handle) ? 0 : -1;
613     free(d);
614   } else {
615     result = -1;
616     SetLastError(ERROR_BAD_ARGUMENTS);
617   }
618   return result;
619 }
620
621 struct dirent *readdir(DIR *d) {
622   struct dirent *result = NULL;
623   if (d != NULL) {
624     memset(&d->result, 0, sizeof(d->result));
625     if (d->handle != INVALID_HANDLE_VALUE) {
626       result = &d->result;
627       WideCharToMultiByte(CP_UTF8, 0, d->info.cFileName, -1, result->d_name,
628                           sizeof(result->d_name), NULL, NULL);
629       if (!FindNextFileW(d->handle, &d->info)) {
630         FindClose(d->handle);
631         d->handle = INVALID_HANDLE_VALUE;
632       }
633     } else {
634       SetLastError(ERROR_FILE_NOT_FOUND);
635     }
636   } else {
637     SetLastError(ERROR_BAD_ARGUMENTS);
638   }
639   return result;
640 }
641 #endif
642
643 static void p_list(const char *dir, void (*fn)(const char *, void *),
644                    void *userdata) {
645 #if MG_ENABLE_DIRLIST
646   struct dirent *dp;
647   DIR *dirp;
648   if ((dirp = (opendir(dir))) == NULL) return;
649   while ((dp = readdir(dirp)) != NULL) {
650     if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue;
651     fn(dp->d_name, userdata);
652   }
653   closedir(dirp);
654 #else
655   (void) dir, (void) fn, (void) userdata;
656 #endif
657 }
658
659 static struct mg_fd *p_open(const char *path, int flags) {
660   const char *mode = flags == (MG_FS_READ | MG_FS_WRITE) ? "r+b"
661                      : flags & MG_FS_READ                ? "rb"
662                      : flags & MG_FS_WRITE               ? "wb"
663                                                          : "";
664   void *fp = NULL;
665   struct mg_fd *fd = NULL;
666 #ifdef _WIN32
667   wchar_t b1[PATH_MAX], b2[10];
668   MultiByteToWideChar(CP_UTF8, 0, path, -1, b1, sizeof(b1) / sizeof(b1[0]));
669   MultiByteToWideChar(CP_UTF8, 0, mode, -1, b2, sizeof(b2) / sizeof(b2[0]));
670   fp = (void *) _wfopen(b1, b2);
671 #else
672   fp = (void *) fopen(path, mode);
673 #endif
674   if (fp == NULL) return NULL;
675   fd = (struct mg_fd *) calloc(1, sizeof(*fd));
676   fd->fd = fp;
677   fd->fs = &mg_fs_posix;
678   return fd;
679 }
680
681 static void p_close(struct mg_fd *fd) {
682   if (fd != NULL) fclose((FILE *) fd->fd), free(fd);
683 }
684
685 static size_t p_read(void *fp, void *buf, size_t len) {
686   return fread(buf, 1, len, (FILE *) fp);
687 }
688
689 static size_t p_write(void *fp, const void *buf, size_t len) {
690   return fwrite(buf, 1, len, (FILE *) fp);
691 }
692
693 static size_t p_seek(void *fp, size_t offset) {
694 #if (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64) || \
695   (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \
696   (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
697   fseeko((FILE *) fp, (off_t) offset, SEEK_SET);
698 #else
699   fseek((FILE *) fp, (long) offset, SEEK_SET);
700 #endif
701   return (size_t) ftell((FILE *) fp);
702 }
703 #else
704 static char *p_realpath(const char *path, char *resolved_path) {
705   (void) path, (void) resolved_path;
706   return NULL;
707 }
708
709 static int p_stat(const char *path, size_t *size, time_t *mtime) {
710   (void) path, (void) size, (void) mtime;
711   return 0;
712 }
713
714 static void p_list(const char *path, void (*fn)(const char *, void *),
715                    void *userdata) {
716   (void) path, (void) fn, (void) userdata;
717 }
718
719 static struct mg_fd *p_open(const char *path, int flags) {
720   (void) path, (void) flags;
721   return NULL;
722 }
723
724 static void p_close(struct mg_fd *fd) {
725   (void) fd;
726 }
727
728 static size_t p_read(void *fd, void *buf, size_t len) {
729   (void) fd, (void) buf, (void) len;
730   return 0;
731 }
732
733 static size_t p_write(void *fd, const void *buf, size_t len) {
734   (void) fd, (void) buf, (void) len;
735   return 0;
736 }
737
738 static size_t p_seek(void *fd, size_t offset) {
739   (void) fd, (void) offset;
740   return (size_t) ~0;
741 }
742 #endif
743
744 struct mg_fs mg_fs_posix = {p_stat, p_list,  p_open, p_close,
745                             p_read, p_write, p_seek};
746
747 #ifdef MG_ENABLE_LINES
748 #line 1 "src/http.c"
749 #endif
750
751
752
753
754
755
756
757
758
759
760 // Multipart POST example:
761 // --xyz
762 // Content-Disposition: form-data; name="val"
763 //
764 // abcdef
765 // --xyz
766 // Content-Disposition: form-data; name="foo"; filename="a.txt"
767 // Content-Type: text/plain
768 //
769 // hello world
770 //
771 // --xyz--
772 size_t mg_http_next_multipart(struct mg_str body, size_t ofs,
773                               struct mg_http_part *part) {
774   struct mg_str cd = mg_str_n("Content-Disposition", 19);
775   const char *s = body.ptr;
776   size_t b = ofs, h1, h2, b1, b2, max = body.len;
777
778   // Init part params
779   if (part != NULL) part->name = part->filename = part->body = mg_str_n(0, 0);
780
781   // Skip boundary
782   while (b + 2 < max && s[b] != '\r' && s[b + 1] != '\n') b++;
783   if (b <= ofs || b + 2 >= max) return 0;
784   // LOG(LL_INFO, ("B: %zu %zu [%.*s]", ofs, b - ofs, (int) (b - ofs), s));
785
786   // Skip headers
787   h1 = h2 = b + 2;
788   for (;;) {
789     while (h2 + 2 < max && s[h2] != '\r' && s[h2 + 1] != '\n') h2++;
790     if (h2 == h1) break;
791     if (h2 + 2 >= max) return 0;
792     // LOG(LL_INFO, ("Header: [%.*s]", (int) (h2 - h1), &s[h1]));
793     if (part != NULL && h1 + cd.len + 2 < h2 && s[h1 + cd.len] == ':' &&
794         mg_ncasecmp(&s[h1], cd.ptr, cd.len) == 0) {
795       struct mg_str v = mg_str_n(&s[h1 + cd.len + 2], h2 - (h1 + cd.len + 2));
796       part->name = mg_http_get_header_var(v, mg_str_n("name", 4));
797       part->filename = mg_http_get_header_var(v, mg_str_n("filename", 8));
798     }
799     h1 = h2 = h2 + 2;
800   }
801   b1 = b2 = h2 + 2;
802   while (b2 + 2 + (b - ofs) + 2 < max && !(s[b2] == '\r' && s[b2 + 1] == '\n' &&
803                                            memcmp(&s[b2 + 2], s, b - ofs) == 0))
804     b2++;
805
806   if (b2 + 2 >= max) return 0;
807   if (part != NULL) part->body = mg_str_n(&s[b1], b2 - b1);
808   // LOG(LL_INFO, ("Body: [%.*s]", (int) (b2 - b1), &s[b1]));
809   return b2 + 2;
810 }
811
812 void mg_http_bauth(struct mg_connection *c, const char *user,
813                    const char *pass) {
814   struct mg_str u = mg_str(user), p = mg_str(pass);
815   size_t need = c->send.len + 36 + (u.len + p.len) * 2;
816   if (c->send.size < need) mg_iobuf_resize(&c->send, need);
817   if (c->send.size >= need) {
818     int i, n = 0;
819     char *buf = (char *) &c->send.buf[c->send.len + 21];
820     memcpy(&buf[-21], "Authorization: Basic ", 21);  // DON'T use mg_send!
821     for (i = 0; i < (int) u.len; i++) {
822       n = mg_base64_update(((unsigned char *) u.ptr)[i], buf, n);
823     }
824     if (p.len > 0) {
825       n = mg_base64_update(':', buf, n);
826       for (i = 0; i < (int) p.len; i++) {
827         n = mg_base64_update(((unsigned char *) p.ptr)[i], buf, n);
828       }
829     }
830     n = mg_base64_final(buf, n);
831     c->send.len += 21 + (size_t) n + 2;
832     memcpy(&c->send.buf[c->send.len - 2], "\r\n", 2);
833   } else {
834     LOG(LL_ERROR, ("%lu %s cannot resize iobuf %d->%d ", c->id, c->label,
835                    (int) c->send.size, (int) need));
836   }
837 }
838
839 int mg_http_get_var(const struct mg_str *buf, const char *name, char *dst,
840                     size_t dst_len) {
841   const char *p, *e, *s;
842   size_t name_len;
843   int len;
844
845   if (dst == NULL || dst_len == 0) {
846     len = -2;  // Bad destination
847   } else if (buf->ptr == NULL || name == NULL || buf->len == 0) {
848     len = -1;  // Bad source
849     dst[0] = '\0';
850   } else {
851     name_len = strlen(name);
852     e = buf->ptr + buf->len;
853     len = -4;  // Name does not exist
854     dst[0] = '\0';
855     for (p = buf->ptr; p + name_len < e; p++) {
856       if ((p == buf->ptr || p[-1] == '&') && p[name_len] == '=' &&
857           !mg_ncasecmp(name, p, name_len)) {
858         p += name_len + 1;
859         s = (const char *) memchr(p, '&', (size_t) (e - p));
860         if (s == NULL) s = e;
861         len = mg_url_decode(p, (size_t) (s - p), dst, dst_len, 1);
862         if (len < 0) len = -3;  // Failed to decode
863         break;
864       }
865     }
866   }
867   return len;
868 }
869
870 int mg_url_decode(const char *src, size_t src_len, char *dst, size_t dst_len,
871                   int is_form_url_encoded) {
872   size_t i, j;
873   for (i = j = 0; i < src_len && j + 1 < dst_len; i++, j++) {
874     if (src[i] == '%') {
875       // Use `i + 2 < src_len`, not `i < src_len - 2`, note small src_len
876       if (i + 2 < src_len && isxdigit(*(const unsigned char *) (src + i + 1)) &&
877           isxdigit(*(const unsigned char *) (src + i + 2))) {
878         mg_unhex(src + i + 1, 2, (uint8_t *) &dst[j]);
879         i += 2;
880       } else {
881         return -1;
882       }
883     } else if (is_form_url_encoded && src[i] == '+') {
884       dst[j] = ' ';
885     } else {
886       dst[j] = src[i];
887     }
888   }
889   if (j < dst_len) dst[j] = '\0';  // Null-terminate the destination
890   return i >= src_len && j < dst_len ? (int) j : -1;
891 }
892
893 int mg_http_get_request_len(const unsigned char *buf, size_t buf_len) {
894   size_t i;
895   for (i = 0; i < buf_len; i++) {
896     if (!isprint(buf[i]) && buf[i] != '\r' && buf[i] != '\n' && buf[i] < 128)
897       return -1;
898     if ((i > 0 && buf[i] == '\n' && buf[i - 1] == '\n') ||
899         (i > 3 && buf[i] == '\n' && buf[i - 1] == '\r' && buf[i - 2] == '\n'))
900       return (int) i + 1;
901   }
902   return 0;
903 }
904
905 static const char *skip(const char *s, const char *e, const char *d,
906                         struct mg_str *v) {
907   v->ptr = s;
908   while (s < e && *s != '\n' && strchr(d, *s) == NULL) s++;
909   v->len = (size_t) (s - v->ptr);
910   while (s < e && strchr(d, *s) != NULL) s++;
911   return s;
912 }
913
914 struct mg_str *mg_http_get_header(struct mg_http_message *h, const char *name) {
915   size_t i, n = strlen(name), max = sizeof(h->headers) / sizeof(h->headers[0]);
916   for (i = 0; i < max && h->headers[i].name.len > 0; i++) {
917     struct mg_str *k = &h->headers[i].name, *v = &h->headers[i].value;
918     if (n == k->len && mg_ncasecmp(k->ptr, name, n) == 0) return v;
919   }
920   return NULL;
921 }
922
923 static void mg_http_parse_headers(const char *s, const char *end,
924                                   struct mg_http_header *h, int max_headers) {
925   int i;
926   for (i = 0; i < max_headers; i++) {
927     struct mg_str k, v, tmp;
928     const char *he = skip(s, end, "\n", &tmp);
929     s = skip(s, he, ": \r\n", &k);
930     s = skip(s, he, "\r\n", &v);
931     if (k.len == tmp.len) continue;
932     while (v.len > 0 && v.ptr[v.len - 1] == ' ') v.len--;  // Trim spaces
933     if (k.len == 0) break;
934     // LOG(LL_INFO, ("--HH [%.*s] [%.*s] [%.*s]", (int) tmp.len - 1, tmp.ptr,
935     //(int) k.len, k.ptr, (int) v.len, v.ptr));
936     h[i].name = k;
937     h[i].value = v;
938   }
939 }
940
941 int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
942   int is_response, req_len = mg_http_get_request_len((unsigned char *) s, len);
943   const char *end = s + req_len, *qs;
944   struct mg_str *cl;
945
946   memset(hm, 0, sizeof(*hm));
947   if (req_len <= 0) return req_len;
948
949   hm->message.ptr = hm->head.ptr = s;
950   hm->body.ptr = end;
951   hm->head.len = (size_t) req_len;
952   hm->chunk.ptr = end;
953   hm->message.len = hm->body.len = (size_t) ~0;  // Set body length to infinite
954
955   // Parse request line
956   s = skip(s, end, " ", &hm->method);
957   s = skip(s, end, " ", &hm->uri);
958   s = skip(s, end, "\r\n", &hm->proto);
959
960   // Sanity check. Allow protocol/reason to be empty
961   if (hm->method.len == 0 || hm->uri.len == 0) return -1;
962
963   // If URI contains '?' character, setup query string
964   if ((qs = (const char *) memchr(hm->uri.ptr, '?', hm->uri.len)) != NULL) {
965     hm->query.ptr = qs + 1;
966     hm->query.len = (size_t) (&hm->uri.ptr[hm->uri.len] - (qs + 1));
967     hm->uri.len = (size_t) (qs - hm->uri.ptr);
968   }
969
970   mg_http_parse_headers(s, end, hm->headers,
971                         sizeof(hm->headers) / sizeof(hm->headers[0]));
972   if ((cl = mg_http_get_header(hm, "Content-Length")) != NULL) {
973     hm->body.len = (size_t) mg_to64(*cl);
974     hm->message.len = (size_t) req_len + hm->body.len;
975   }
976
977   // mg_http_parse() is used to parse both HTTP requests and HTTP
978   // responses. If HTTP response does not have Content-Length set, then
979   // body is read until socket is closed, i.e. body.len is infinite (~0).
980   //
981   // For HTTP requests though, according to
982   // http://tools.ietf.org/html/rfc7231#section-8.1.3,
983   // only POST and PUT methods have defined body semantics.
984   // Therefore, if Content-Length is not specified and methods are
985   // not one of PUT or POST, set body length to 0.
986   //
987   // So, if it is HTTP request, and Content-Length is not set,
988   // and method is not (PUT or POST) then reset body length to zero.
989   is_response = mg_ncasecmp(hm->method.ptr, "HTTP/", 5) == 0;
990   if (hm->body.len == (size_t) ~0 && !is_response &&
991       mg_vcasecmp(&hm->method, "PUT") != 0 &&
992       mg_vcasecmp(&hm->method, "POST") != 0) {
993     hm->body.len = 0;
994     hm->message.len = (size_t) req_len;
995   }
996
997   // The 204 (No content) responses also have 0 body length
998   if (hm->body.len == (size_t) ~0 && is_response &&
999       mg_vcasecmp(&hm->uri, "204") == 0) {
1000     hm->body.len = 0;
1001     hm->message.len = (size_t) req_len;
1002   }
1003
1004   return req_len;
1005 }
1006
1007 static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt,
1008                                   va_list ap) {
1009   char mem[256], *buf = mem;
1010   int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
1011   mg_printf(c, "%X\r\n", len);
1012   mg_send(c, buf, len > 0 ? (size_t) len : 0);
1013   mg_send(c, "\r\n", 2);
1014   if (buf != mem) free(buf);
1015 }
1016
1017 void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...) {
1018   va_list ap;
1019   va_start(ap, fmt);
1020   mg_http_vprintf_chunk(c, fmt, ap);
1021   va_end(ap);
1022 }
1023
1024 void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len) {
1025   mg_printf(c, "%lX\r\n", (unsigned long) len);
1026   mg_send(c, buf, len);
1027   mg_send(c, "\r\n", 2);
1028 }
1029
1030 // clang-format off
1031 static const char *mg_http_status_code_str(int status_code) {
1032   switch (status_code) {
1033     case 100: return "Continue";
1034     case 101: return "Switching Protocols";
1035     case 102: return "Processing";
1036     case 200: return "OK";
1037     case 201: return "Created";
1038     case 202: return "Accepted";
1039     case 203: return "Non-authoritative Information";
1040     case 204: return "No Content";
1041     case 205: return "Reset Content";
1042     case 206: return "Partial Content";
1043     case 207: return "Multi-Status";
1044     case 208: return "Already Reported";
1045     case 226: return "IM Used";
1046     case 300: return "Multiple Choices";
1047     case 301: return "Moved Permanently";
1048     case 302: return "Found";
1049     case 303: return "See Other";
1050     case 304: return "Not Modified";
1051     case 305: return "Use Proxy";
1052     case 307: return "Temporary Redirect";
1053     case 308: return "Permanent Redirect";
1054     case 400: return "Bad Request";
1055     case 401: return "Unauthorized";
1056     case 402: return "Payment Required";
1057     case 403: return "Forbidden";
1058     case 404: return "Not Found";
1059     case 405: return "Method Not Allowed";
1060     case 406: return "Not Acceptable";
1061     case 407: return "Proxy Authentication Required";
1062     case 408: return "Request Timeout";
1063     case 409: return "Conflict";
1064     case 410: return "Gone";
1065     case 411: return "Length Required";
1066     case 412: return "Precondition Failed";
1067     case 413: return "Payload Too Large";
1068     case 414: return "Request-URI Too Long";
1069     case 415: return "Unsupported Media Type";
1070     case 416: return "Requested Range Not Satisfiable";
1071     case 417: return "Expectation Failed";
1072     case 418: return "I'm a teapot";
1073     case 421: return "Misdirected Request";
1074     case 422: return "Unprocessable Entity";
1075     case 423: return "Locked";
1076     case 424: return "Failed Dependency";
1077     case 426: return "Upgrade Required";
1078     case 428: return "Precondition Required";
1079     case 429: return "Too Many Requests";
1080     case 431: return "Request Header Fields Too Large";
1081     case 444: return "Connection Closed Without Response";
1082     case 451: return "Unavailable For Legal Reasons";
1083     case 499: return "Client Closed Request";
1084     case 500: return "Internal Server Error";
1085     case 501: return "Not Implemented";
1086     case 502: return "Bad Gateway";
1087     case 503: return "Service Unavailable";
1088     case 504: return "Gateway Timeout";
1089     case 505: return "HTTP Version Not Supported";
1090     case 506: return "Variant Also Negotiates";
1091     case 507: return "Insufficient Storage";
1092     case 508: return "Loop Detected";
1093     case 510: return "Not Extended";
1094     case 511: return "Network Authentication Required";
1095     case 599: return "Network Connect Timeout Error";
1096     default: return "OK";
1097   }
1098 }
1099 // clang-format on
1100
1101 void mg_http_reply(struct mg_connection *c, int code, const char *headers,
1102                    const char *fmt, ...) {
1103   char mem[256], *buf = mem;
1104   va_list ap;
1105   int len;
1106   va_start(ap, fmt);
1107   len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
1108   va_end(ap);
1109   mg_printf(c, "HTTP/1.1 %d %s\r\n%sContent-Length: %d\r\n\r\n", code,
1110             mg_http_status_code_str(code), headers == NULL ? "" : headers, len);
1111   mg_send(c, buf, len > 0 ? (size_t) len : 0);
1112   if (buf != mem) free(buf);
1113 }
1114
1115 static void http_cb(struct mg_connection *, int, void *, void *);
1116 static void restore_http_cb(struct mg_connection *c) {
1117   struct mg_fd *fd = (struct mg_fd *) c->pfn_data;
1118   if (fd != NULL) fd->fs->close(fd);
1119   c->pfn_data = NULL;
1120   c->pfn = http_cb;
1121 }
1122
1123 char *mg_http_etag(char *buf, size_t len, size_t size, time_t mtime);
1124 char *mg_http_etag(char *buf, size_t len, size_t size, time_t mtime) {
1125   snprintf(buf, len, "\"%lx." MG_INT64_FMT "\"", (unsigned long) mtime,
1126            (int64_t) size);
1127   return buf;
1128 }
1129
1130 int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
1131                    const char *dir) {
1132   char offset[40] = "", name[200] = "", path[256];
1133   mg_http_get_var(&hm->query, "offset", offset, sizeof(offset));
1134   mg_http_get_var(&hm->query, "name", name, sizeof(name));
1135   if (name[0] == '\0') {
1136     mg_http_reply(c, 400, "", "%s", "name required");
1137     return -1;
1138   } else {
1139     FILE *fp;
1140     size_t oft = strtoul(offset, NULL, 0);
1141     snprintf(path, sizeof(path), "%s%c%s", dir, MG_DIRSEP, name);
1142     LOG(LL_DEBUG,
1143         ("%p %d bytes @ %d [%s]", c->fd, (int) hm->body.len, (int) oft, name));
1144     if ((fp = fopen(path, oft == 0 ? "wb" : "ab")) == NULL) {
1145       mg_http_reply(c, 400, "", "fopen(%s): %d", name, errno);
1146       return -2;
1147     } else {
1148       fwrite(hm->body.ptr, 1, hm->body.len, fp);
1149       fclose(fp);
1150       mg_http_reply(c, 200, "", "");
1151       return (int) hm->body.len;
1152     }
1153   }
1154 }
1155
1156 static void static_cb(struct mg_connection *c, int ev, void *ev_data,
1157                       void *fn_data) {
1158   if (ev == MG_EV_WRITE || ev == MG_EV_POLL) {
1159     struct mg_fd *fd = (struct mg_fd *) fn_data;
1160     // Read to send IO buffer directly, avoid extra on-stack buffer
1161     size_t n, max = 2 * MG_IO_SIZE;
1162     if (c->send.size < max) mg_iobuf_resize(&c->send, max);
1163     if (c->send.len >= c->send.size) return;  // Rate limit
1164     n = fd->fs->read(fd->fd, c->send.buf + c->send.len,
1165                      c->send.size - c->send.len);
1166     if (n > 0) c->send.len += n;
1167     if (c->send.len < c->send.size) restore_http_cb(c);
1168   } else if (ev == MG_EV_CLOSE) {
1169     restore_http_cb(c);
1170   }
1171   (void) ev_data;
1172 }
1173
1174 static struct mg_str guess_content_type(struct mg_str path, const char *extra) {
1175   // clang-format off
1176   struct mimeentry { struct mg_str extension, value; };
1177   #define MIME_ENTRY(a, b) {{a, sizeof(a) - 1 }, { b, sizeof(b) - 1 }}
1178   // clang-format on
1179   const struct mimeentry tab[] = {
1180       MIME_ENTRY("html", "text/html; charset=utf-8"),
1181       MIME_ENTRY("htm", "text/html; charset=utf-8"),
1182       MIME_ENTRY("css", "text/css; charset=utf-8"),
1183       MIME_ENTRY("js", "text/javascript; charset=utf-8"),
1184       MIME_ENTRY("gif", "image/gif"),
1185       MIME_ENTRY("png", "image/png"),
1186       MIME_ENTRY("jpg", "image/jpeg"),
1187       MIME_ENTRY("jpeg", "image/jpeg"),
1188       MIME_ENTRY("woff", "font/woff"),
1189       MIME_ENTRY("ttf", "font/ttf"),
1190       MIME_ENTRY("svg", "image/svg+xml"),
1191       MIME_ENTRY("txt", "text/plain; charset=utf-8"),
1192       MIME_ENTRY("avi", "video/x-msvideo"),
1193       MIME_ENTRY("csv", "text/csv"),
1194       MIME_ENTRY("doc", "application/msword"),
1195       MIME_ENTRY("exe", "application/octet-stream"),
1196       MIME_ENTRY("gz", "application/gzip"),
1197       MIME_ENTRY("ico", "image/x-icon"),
1198       MIME_ENTRY("json", "application/json"),
1199       MIME_ENTRY("mov", "video/quicktime"),
1200       MIME_ENTRY("mp3", "audio/mpeg"),
1201       MIME_ENTRY("mp4", "video/mp4"),
1202       MIME_ENTRY("mpeg", "video/mpeg"),
1203       MIME_ENTRY("pdf", "application/pdf"),
1204       MIME_ENTRY("shtml", "text/html; charset=utf-8"),
1205       MIME_ENTRY("tgz", "application/tar-gz"),
1206       MIME_ENTRY("wav", "audio/wav"),
1207       MIME_ENTRY("webp", "image/webp"),
1208       MIME_ENTRY("zip", "application/zip"),
1209       MIME_ENTRY("3gp", "video/3gpp"),
1210       {{0, 0}, {0, 0}},
1211   };
1212   size_t i = 0;
1213   struct mg_str k, v, s = mg_str(extra);
1214
1215   // Shrink path to its extension only
1216   while (i < path.len && path.ptr[path.len - i - 1] != '.') i++;
1217   path.ptr += path.len - i;
1218   path.len = i;
1219
1220   // Process user-provided mime type overrides, if any
1221   while (mg_commalist(&s, &k, &v)) {
1222     if (mg_strcmp(path, k) == 0) return v;
1223   }
1224
1225   // Process built-in mime types
1226   for (i = 0; tab[i].extension.ptr != NULL; i++) {
1227     if (mg_strcmp(path, tab[i].extension) == 0) return tab[i].value;
1228   }
1229
1230   return mg_str("text/plain; charset=utf-8");
1231 }
1232
1233 static int getrange(struct mg_str *s, int64_t *a, int64_t *b) {
1234   size_t i, numparsed = 0;
1235   LOG(LL_INFO, ("%.*s", (int) s->len, s->ptr));
1236   for (i = 0; i + 6 < s->len; i++) {
1237     if (memcmp(&s->ptr[i], "bytes=", 6) == 0) {
1238       struct mg_str p = mg_str_n(s->ptr + i + 6, s->len - i - 6);
1239       if (p.len > 0 && p.ptr[0] >= '0' && p.ptr[0] <= '9') numparsed++;
1240       *a = mg_to64(p);
1241       // LOG(LL_INFO, ("PPP [%.*s] %d", (int) p.len, p.ptr, numparsed));
1242       while (p.len && p.ptr[0] >= '0' && p.ptr[0] <= '9') p.ptr++, p.len--;
1243       if (p.len && p.ptr[0] == '-') p.ptr++, p.len--;
1244       *b = mg_to64(p);
1245       if (p.len > 0 && p.ptr[0] >= '0' && p.ptr[0] <= '9') numparsed++;
1246       // LOG(LL_INFO, ("PPP [%.*s] %d", (int) p.len, p.ptr, numparsed));
1247       break;
1248     }
1249   }
1250   return (int) numparsed;
1251 }
1252
1253 void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
1254                         const char *path, struct mg_http_serve_opts *opts) {
1255   char etag[64];
1256   struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
1257   struct mg_fd *fd = fs->open(path, MG_FS_READ);
1258   size_t size = 0;
1259   time_t mtime = 0;
1260   struct mg_str *inm = NULL;
1261
1262   if (fd == NULL || fs->stat(path, &size, &mtime) == 0) {
1263     LOG(LL_DEBUG, ("404 [%s] %p", path, (void *) fd));
1264     mg_http_reply(c, 404, "", "%s", "Not found\n");
1265     fs->close(fd);
1266     // NOTE: mg_http_etag() call should go first!
1267   } else if (mg_http_etag(etag, sizeof(etag), size, mtime) != NULL &&
1268              (inm = mg_http_get_header(hm, "If-None-Match")) != NULL &&
1269              mg_vcasecmp(inm, etag) == 0) {
1270     fs->close(fd);
1271     mg_printf(c, "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n");
1272   } else {
1273     int n, status = 200;
1274     char range[100] = "";
1275     int64_t r1 = 0, r2 = 0, cl = (int64_t) size;
1276     struct mg_str mime = guess_content_type(mg_str(path), opts->mime_types);
1277
1278     // Handle Range header
1279     struct mg_str *rh = mg_http_get_header(hm, "Range");
1280     if (rh != NULL && (n = getrange(rh, &r1, &r2)) > 0 && r1 >= 0 && r2 >= 0) {
1281       // If range is specified like "400-", set second limit to content len
1282       if (n == 1) r2 = cl - 1;
1283       if (r1 > r2 || r2 >= cl) {
1284         status = 416;
1285         cl = 0;
1286         snprintf(range, sizeof(range),
1287                  "Content-Range: bytes */" MG_INT64_FMT "\r\n", (int64_t) size);
1288       } else {
1289         status = 206;
1290         cl = r2 - r1 + 1;
1291         snprintf(range, sizeof(range),
1292                  "Content-Range: bytes " MG_INT64_FMT "-" MG_INT64_FMT
1293                  "/" MG_INT64_FMT "\r\n",
1294                  r1, r1 + cl - 1, (int64_t) size);
1295         fs->seek(fd->fd, (size_t) r1);
1296       }
1297     }
1298
1299     mg_printf(c,
1300               "HTTP/1.1 %d %s\r\nContent-Type: %.*s\r\n"
1301               "Etag: %s\r\nContent-Length: " MG_INT64_FMT "\r\n%s%s\r\n",
1302               status, mg_http_status_code_str(status), (int) mime.len, mime.ptr,
1303               etag, cl, range, opts->extra_headers ? opts->extra_headers : "");
1304     if (mg_vcasecmp(&hm->method, "HEAD") == 0) {
1305       c->is_draining = 1;
1306       fs->close(fd);
1307     } else {
1308       c->pfn = static_cb;
1309       c->pfn_data = fd;
1310     }
1311   }
1312 }
1313
1314 struct printdirentrydata {
1315   struct mg_connection *c;
1316   struct mg_http_message *hm;
1317   struct mg_http_serve_opts *opts;
1318   const char *dir;
1319 };
1320
1321 static void printdirentry(const char *name, void *userdata) {
1322   struct printdirentrydata *d = (struct printdirentrydata *) userdata;
1323   struct mg_fs *fs = d->opts->fs == NULL ? &mg_fs_posix : d->opts->fs;
1324   size_t size = 0;
1325   time_t t = 0;
1326   char path[MG_PATH_MAX], sz[64], mod[64];
1327   int flags, n = 0;
1328
1329   // LOG(LL_DEBUG, ("[%s] [%s]", d->dir, name));
1330   if (snprintf(path, sizeof(path), "%s%c%s", d->dir, '/', name) < 0) {
1331     LOG(LL_ERROR, ("%s truncated", name));
1332   } else if ((flags = fs->stat(path, &size, &t)) == 0) {
1333     LOG(LL_ERROR, ("%lu stat(%s): %d", d->c->id, path, errno));
1334   } else {
1335     const char *slash = flags & MG_FS_DIR ? "/" : "";
1336     struct tm tm;
1337     if (flags & MG_FS_DIR) {
1338       snprintf(sz, sizeof(sz), "%s", "[DIR]");
1339     } else if (size < 1024) {
1340       snprintf(sz, sizeof(sz), "%d", (int) size);
1341     } else if (size < 0x100000) {
1342       snprintf(sz, sizeof(sz), "%.1fk", (double) size / 1024.0);
1343     } else if (size < 0x40000000) {
1344       snprintf(sz, sizeof(sz), "%.1fM", (double) size / 1048576);
1345     } else {
1346       snprintf(sz, sizeof(sz), "%.1fG", (double) size / 1073741824);
1347     }
1348     strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime_r(&t, &tm));
1349     n = (int) mg_url_encode(name, strlen(name), path, sizeof(path));
1350     mg_printf(d->c,
1351               "  <tr><td><a href=\"%.*s%s\">%s%s</a></td>"
1352               "<td name=%lu>%s</td><td name=" MG_INT64_FMT ">%s</td></tr>\n",
1353               n, path, slash, name, slash, (unsigned long) t, mod,
1354               flags & MG_FS_DIR ? (int64_t) -1 : (int64_t) size, sz);
1355   }
1356 }
1357
1358 static void listdir(struct mg_connection *c, struct mg_http_message *hm,
1359                     struct mg_http_serve_opts *opts, char *dir) {
1360   static const char *sort_js_code =
1361       "<script>function srt(tb, sc, so, d) {"
1362       "var tr = Array.prototype.slice.call(tb.rows, 0),"
1363       "tr = tr.sort(function (a, b) { var c1 = a.cells[sc], c2 = b.cells[sc],"
1364       "n1 = c1.getAttribute('name'), n2 = c2.getAttribute('name'), "
1365       "t1 = a.cells[2].getAttribute('name'), "
1366       "t2 = b.cells[2].getAttribute('name'); "
1367       "return so * (t1 < 0 && t2 >= 0 ? -1 : t2 < 0 && t1 >= 0 ? 1 : "
1368       "n1 ? parseInt(n2) - parseInt(n1) : "
1369       "c1.textContent.trim().localeCompare(c2.textContent.trim())); });";
1370   static const char *sort_js_code2 =
1371       "for (var i = 0; i < tr.length; i++) tb.appendChild(tr[i]); "
1372       "if (!d) window.location.hash = ('sc=' + sc + '&so=' + so); "
1373       "};"
1374       "window.onload = function() {"
1375       "var tb = document.getElementById('tb');"
1376       "var m = /sc=([012]).so=(1|-1)/.exec(window.location.hash) || [0, 2, 1];"
1377       "var sc = m[1], so = m[2]; document.onclick = function(ev) { "
1378       "var c = ev.target.rel; if (c) {if (c == sc) so *= -1; srt(tb, c, so); "
1379       "sc = c; ev.preventDefault();}};"
1380       "srt(tb, sc, so, true);"
1381       "}"
1382       "</script>";
1383   struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
1384   struct printdirentrydata d = {c, hm, opts, dir};
1385   char tmp[10], buf[MG_PATH_MAX];
1386   size_t off, n;
1387   int len = mg_url_decode(hm->uri.ptr, hm->uri.len, buf, sizeof(buf), 0);
1388   struct mg_str uri = len > 0 ? mg_str_n(buf, (size_t) len) : hm->uri;
1389
1390   mg_printf(c,
1391             "HTTP/1.1 200 OK\r\n"
1392             "Content-Type: text/html; charset=utf-8\r\n"
1393             "%s"
1394             "Content-Length:         \r\n\r\n",
1395             opts->extra_headers == NULL ? "" : opts->extra_headers);
1396   off = c->send.len;  // Start of body
1397   mg_printf(c,
1398             "<!DOCTYPE html><html><head><title>Index of %.*s</title>%s%s"
1399             "<style>th,td {text-align: left; padding-right: 1em; "
1400             "font-family: monospace; }</style></head>"
1401             "<body><h1>Index of %.*s</h1><table cellpadding=\"0\"><thead>"
1402             "<tr><th><a href=\"#\" rel=\"0\">Name</a></th><th>"
1403             "<a href=\"#\" rel=\"1\">Modified</a></th>"
1404             "<th><a href=\"#\" rel=\"2\">Size</a></th></tr>"
1405             "<tr><td colspan=\"3\"><hr></td></tr>"
1406             "</thead>"
1407             "<tbody id=\"tb\">\n",
1408             (int) uri.len, uri.ptr, sort_js_code, sort_js_code2, (int) uri.len,
1409             uri.ptr);
1410
1411   fs->list(dir, printdirentry, &d);
1412   mg_printf(c,
1413             "</tbody><tfoot><tr><td colspan=\"3\"><hr></td></tr></tfoot>"
1414             "</table><address>Mongoose v.%s</address></body></html>\n",
1415             MG_VERSION);
1416   n = (size_t) snprintf(tmp, sizeof(tmp), "%lu",
1417                         (unsigned long) (c->send.len - off));
1418   if (n > sizeof(tmp)) n = 0;
1419   memcpy(c->send.buf + off - 10, tmp, n);  // Set content length
1420 }
1421
1422 static void remove_double_dots(char *s) {
1423   char *p = s;
1424   while (*s != '\0') {
1425     *p++ = *s++;
1426     if (s[-1] == '/' || s[-1] == '\\') {
1427       while (s[0] != '\0') {
1428         if (s[0] == '/' || s[0] == '\\') {
1429           s++;
1430         } else if (s[0] == '.' && s[1] == '.' &&
1431                    (s[2] == '/' || s[2] == '\\')) {
1432           s += 2;
1433         } else {
1434           break;
1435         }
1436       }
1437     }
1438   }
1439   *p = '\0';
1440 }
1441
1442 // Resolve requested file into `path` and return its fs->stat() result
1443 static int uri_to_path2(struct mg_connection *c, struct mg_http_message *hm,
1444                         struct mg_fs *fs, struct mg_str url, struct mg_str dir,
1445                         char *path, size_t path_size) {
1446   int flags = 0, tmp;
1447   // Append URI to the root_dir, and sanitize it
1448   size_t n = (size_t) snprintf(path, path_size, "%.*s", (int) dir.len, dir.ptr);
1449   if (n > path_size) n = path_size;
1450   path[path_size - 1] = '\0';
1451   if ((fs->stat(path, NULL, NULL) & MG_FS_DIR) == 0) {
1452     mg_http_reply(c, 400, "", "Invalid web root [%.*s]\n", (int) dir.len,
1453                   dir.ptr);
1454   } else {
1455     if (n + 2 < path_size) path[n++] = '/', path[n] = '\0';
1456     mg_url_decode(hm->uri.ptr + url.len, hm->uri.len - url.len, path + n,
1457                   path_size - n, 0);
1458     path[path_size - 1] = '\0';  // Double-check
1459     remove_double_dots(path);
1460     n = strlen(path);
1461     LOG(LL_VERBOSE_DEBUG,
1462         ("%lu %.*s -> %s", c->id, (int) hm->uri.len, hm->uri.ptr, path));
1463     while (n > 0 && path[n - 1] == '/') path[--n] = 0;  // Trim trailing slashes
1464     flags = fs->stat(path, NULL, NULL);                 // Does it exist?
1465     if (flags == 0) {
1466       mg_http_reply(c, 404, "", "Not found\n");  // Does not exist, doh
1467     } else if ((flags & MG_FS_DIR) && hm->uri.len > 0 &&
1468                hm->uri.ptr[hm->uri.len - 1] != '/') {
1469       mg_printf(c,
1470                 "HTTP/1.1 301 Moved\r\n"
1471                 "Location: %.*s/\r\n"
1472                 "Content-Length: 0\r\n"
1473                 "\r\n",
1474                 (int) hm->uri.len, hm->uri.ptr);
1475       flags = 0;
1476     } else if (flags & MG_FS_DIR) {
1477       if (((snprintf(path + n, path_size - n, "/" MG_HTTP_INDEX) > 0 &&
1478             (tmp = fs->stat(path, NULL, NULL)) != 0) ||
1479            (snprintf(path + n, path_size - n, "/index.shtml") > 0 &&
1480             (tmp = fs->stat(path, NULL, NULL)) != 0))) {
1481         flags = tmp;
1482       } else {
1483         path[n] = '\0';  // Remove appended index file name
1484       }
1485     }
1486   }
1487   return flags;
1488 }
1489
1490 static int uri_to_path(struct mg_connection *c, struct mg_http_message *hm,
1491                        struct mg_http_serve_opts *opts, char *path,
1492                        size_t path_size) {
1493   struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
1494   struct mg_str k, v, s = mg_str(opts->root_dir), u = {0, 0}, p = {0, 0};
1495   while (mg_commalist(&s, &k, &v)) {
1496     if (v.len == 0) v = k, k = mg_str("/");
1497     if (hm->uri.len < k.len) continue;
1498     if (mg_strcmp(k, mg_str_n(hm->uri.ptr, k.len)) != 0) continue;
1499     u = k, p = v;
1500   }
1501   return uri_to_path2(c, hm, fs, u, p, path, path_size);
1502 }
1503
1504 void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
1505                        struct mg_http_serve_opts *opts) {
1506   char path[MG_PATH_MAX] = "";
1507   const char *sp = opts->ssi_pattern;
1508   int flags = uri_to_path(c, hm, opts, path, sizeof(path));
1509   if (flags == 0) return;
1510   LOG(LL_VERBOSE_DEBUG,
1511       ("%.*s %s %d", (int) hm->uri.len, hm->uri.ptr, path, flags));
1512   if (flags & MG_FS_DIR) {
1513     listdir(c, hm, opts, path);
1514   } else if (sp != NULL && mg_globmatch(sp, strlen(sp), path, strlen(path))) {
1515     mg_http_serve_ssi(c, opts->root_dir, path);
1516   } else {
1517     mg_http_serve_file(c, hm, path, opts);
1518   }
1519 }
1520
1521 static bool mg_is_url_safe(int c) {
1522   return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
1523          (c >= 'A' && c <= 'Z') || c == '.' || c == '_' || c == '-' || c == '~';
1524 }
1525
1526 size_t mg_url_encode(const char *s, size_t sl, char *buf, size_t len) {
1527   size_t i, n = 0;
1528   for (i = 0; i < sl; i++) {
1529     int c = *(unsigned char *) &s[i];
1530     if (n + 4 >= len) return 0;
1531     if (mg_is_url_safe(c)) {
1532       buf[n++] = s[i];
1533     } else {
1534       buf[n++] = '%';
1535       mg_hex(&s[i], 1, &buf[n]);
1536       n += 2;
1537     }
1538   }
1539   return n;
1540 }
1541
1542 void mg_http_creds(struct mg_http_message *hm, char *user, size_t userlen,
1543                    char *pass, size_t passlen) {
1544   struct mg_str *v = mg_http_get_header(hm, "Authorization");
1545   user[0] = pass[0] = '\0';
1546   if (v != NULL && v->len > 6 && memcmp(v->ptr, "Basic ", 6) == 0) {
1547     char buf[256];
1548     int n = mg_base64_decode(v->ptr + 6, (int) v->len - 6, buf);
1549     const char *p = (const char *) memchr(buf, ':', n > 0 ? (size_t) n : 0);
1550     if (p != NULL) {
1551       snprintf(user, userlen, "%.*s", (int) (p - buf), buf);
1552       snprintf(pass, passlen, "%.*s", n - (int) (p - buf) - 1, p + 1);
1553     }
1554   } else if (v != NULL && v->len > 7 && memcmp(v->ptr, "Bearer ", 7) == 0) {
1555     snprintf(pass, passlen, "%.*s", (int) v->len - 7, v->ptr + 7);
1556   } else if ((v = mg_http_get_header(hm, "Cookie")) != NULL) {
1557     struct mg_str t = mg_http_get_header_var(*v, mg_str_n("access_token", 12));
1558     if (t.len > 0) snprintf(pass, passlen, "%.*s", (int) t.len, t.ptr);
1559   } else {
1560     mg_http_get_var(&hm->query, "access_token", pass, passlen);
1561   }
1562 }
1563
1564 static struct mg_str stripquotes(struct mg_str s) {
1565   return s.len > 1 && s.ptr[0] == '"' && s.ptr[s.len - 1] == '"'
1566              ? mg_str_n(s.ptr + 1, s.len - 2)
1567              : s;
1568 }
1569
1570 struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v) {
1571   size_t i;
1572   for (i = 0; v.len > 0 && i + v.len + 2 < s.len; i++) {
1573     if (s.ptr[i + v.len] == '=' && memcmp(&s.ptr[i], v.ptr, v.len) == 0) {
1574       const char *p = &s.ptr[i + v.len + 1], *b = p, *x = &s.ptr[s.len];
1575       int q = p < x && *p == '"' ? 1 : 0;
1576       while (p < x &&
1577              (q ? p == b || *p != '"' : *p != ';' && *p != ' ' && *p != ','))
1578         p++;
1579       // LOG(LL_INFO, ("[%.*s] [%.*s] [%.*s]", (int) s.len, s.ptr, (int) v.len,
1580       // v.ptr, (int) (p - b), b));
1581       return stripquotes(mg_str_n(b, (size_t) (p - b + q)));
1582     }
1583   }
1584   return mg_str_n(NULL, 0);
1585 }
1586
1587 bool mg_http_match_uri(const struct mg_http_message *hm, const char *glob) {
1588   return mg_globmatch(glob, strlen(glob), hm->uri.ptr, hm->uri.len);
1589 }
1590
1591 static size_t get_chunk_length(const char *buf, size_t len, size_t *ll) {
1592   size_t i = 0, n;
1593   while (i < len && buf[i] != '\r' && i != '\n') i++;
1594   n = mg_unhexn((char *) buf, i);
1595   while (i < len && (buf[i] == '\r' || i == '\n')) i++;
1596   // LOG(LL_INFO, ("len %zu i %zu n %zu ", len, i, n));
1597   if (ll != NULL) *ll = i + 1;
1598   if (i < len && i + n + 2 < len) return i + n + 3;
1599   return 0;
1600 }
1601
1602 // Walk through all chunks in the chunked body. For each chunk, fire
1603 // an MG_EV_HTTP_CHUNK event.
1604 static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
1605                        size_t reqlen) {
1606   size_t off = 0, bl, ll;
1607   while (off + reqlen < c->recv.len) {
1608     char *buf = (char *) &c->recv.buf[reqlen];
1609     size_t memo = c->recv.len;
1610     size_t cl = get_chunk_length(&buf[off], memo - reqlen - off, &ll);
1611     // LOG(LL_INFO, ("len %zu off %zu cl %zu ll %zu", len, off, cl, ll));
1612     if (cl == 0) break;
1613     hm->chunk = mg_str_n(&buf[off + ll], cl < ll + 2 ? 0 : cl - ll - 2);
1614     mg_call(c, MG_EV_HTTP_CHUNK, hm);
1615     // Increase offset only if user has not deleted this chunk
1616     if (memo == c->recv.len) off += cl;
1617     if (cl <= 5) {
1618       // Zero chunk - last one. Prepare body - cut off chunk lengths
1619       off = bl = 0;
1620       while (off + reqlen < c->recv.len) {
1621         char *buf2 = (char *) &c->recv.buf[reqlen];
1622         size_t memo2 = c->recv.len;
1623         size_t cl2 = get_chunk_length(&buf2[off], memo2 - reqlen - off, &ll);
1624         size_t n = cl2 < ll + 2 ? 0 : cl2 - ll - 2;
1625         memmove(buf2 + bl, buf2 + off + ll, n);
1626         bl += n;
1627         off += cl2;
1628         if (cl2 <= 5) break;
1629       }
1630       // LOG(LL_INFO, ("BL->%d del %d off %d", (int) bl, (int) del, (int) off));
1631       c->recv.len -= off - bl;
1632       // Set message length to indicate we've received
1633       // everything, to fire MG_EV_HTTP_MSG
1634       hm->message.len = bl + reqlen;
1635       hm->body.len = bl;
1636       break;
1637     }
1638   }
1639 }
1640
1641 static bool mg_is_chunked(struct mg_http_message *hm) {
1642   struct mg_str needle = mg_str_n("chunked", 7);
1643   struct mg_str *te = mg_http_get_header(hm, "Transfer-Encoding");
1644   return te != NULL && mg_strstr(*te, needle) != NULL;
1645 }
1646
1647 void mg_http_delete_chunk(struct mg_connection *c, struct mg_http_message *hm) {
1648   struct mg_str ch = hm->chunk;
1649   if (mg_is_chunked(hm)) {
1650     ch.len += 4;  // \r\n before and after the chunk
1651     ch.ptr -= 2;
1652     while (ch.ptr > hm->body.ptr && *ch.ptr != '\n') ch.ptr--, ch.len++;
1653   }
1654   {
1655     const char *end = &ch.ptr[ch.len];
1656     size_t n = (size_t) (end - (char *) c->recv.buf);
1657     if (c->recv.len > n) {
1658       memmove((char *) ch.ptr, end, (size_t) (c->recv.len - n));
1659     }
1660     // LOG(LL_INFO, ("DELETING CHUNK: %zu %zu %zu\n%.*s", c->recv.len, n,
1661     // ch.len, (int) ch.len, ch.ptr));
1662   }
1663   c->recv.len -= ch.len;
1664 }
1665
1666 static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
1667   if (ev == MG_EV_READ || ev == MG_EV_CLOSE) {
1668     struct mg_http_message hm;
1669     for (;;) {
1670       int n = mg_http_parse((char *) c->recv.buf, c->recv.len, &hm);
1671       bool is_chunked = n > 0 && mg_is_chunked(&hm);
1672       if (ev == MG_EV_CLOSE) {
1673         hm.message.len = c->recv.len;
1674         hm.body.len = hm.message.len - (size_t) (hm.body.ptr - hm.message.ptr);
1675       } else if (is_chunked && n > 0) {
1676         walkchunks(c, &hm, (size_t) n);
1677       }
1678       // LOG(LL_INFO,
1679       //("---->%d %d\n%.*s", n, is_chunked, (int) c->recv.len, c->recv.buf));
1680       if (n < 0 && ev == MG_EV_READ) {
1681         mg_error(c, "HTTP parse:\n%.*s", (int) c->recv.len, c->recv.buf);
1682         break;
1683       } else if (n > 0 && (size_t) c->recv.len >= hm.message.len) {
1684         mg_call(c, MG_EV_HTTP_MSG, &hm);
1685         mg_iobuf_del(&c->recv, 0, hm.message.len);
1686       } else {
1687         if (n > 0 && !is_chunked) {
1688           hm.chunk =
1689               mg_str_n((char *) &c->recv.buf[n], c->recv.len - (size_t) n);
1690           mg_call(c, MG_EV_HTTP_CHUNK, &hm);
1691         }
1692         break;
1693       }
1694     }
1695   }
1696   (void) fnd;
1697   (void) evd;
1698 }
1699
1700 struct mg_connection *mg_http_connect(struct mg_mgr *mgr, const char *url,
1701                                       mg_event_handler_t fn, void *fn_data) {
1702   struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
1703   if (c != NULL) c->pfn = http_cb;
1704   return c;
1705 }
1706
1707 struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url,
1708                                      mg_event_handler_t fn, void *fn_data) {
1709   struct mg_connection *c = mg_listen(mgr, url, fn, fn_data);
1710   if (c != NULL) c->pfn = http_cb;
1711   return c;
1712 }
1713
1714 #ifdef MG_ENABLE_LINES
1715 #line 1 "src/iobuf.c"
1716 #endif
1717
1718
1719
1720 #include <string.h>
1721
1722 // Not using memset for zeroing memory, cause it can be dropped by compiler
1723 // See https://github.com/cesanta/mongoose/pull/1265
1724 static void zeromem(volatile unsigned char *buf, size_t len) {
1725   if (buf != NULL) {
1726     while (len--) *buf++ = 0;
1727   }
1728 }
1729
1730 int mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) {
1731   int ok = 1;
1732   if (new_size == 0) {
1733     zeromem(io->buf, io->size);
1734     free(io->buf);
1735     io->buf = NULL;
1736     io->len = io->size = 0;
1737   } else if (new_size != io->size) {
1738     // NOTE(lsm): do not use realloc here. Use calloc/free only, to ease the
1739     // porting to some obscure platforms like FreeRTOS
1740     void *p = calloc(1, new_size);
1741     if (p != NULL) {
1742       size_t len = new_size < io->len ? new_size : io->len;
1743       if (len > 0) memcpy(p, io->buf, len);
1744       zeromem(io->buf, io->size);
1745       free(io->buf);
1746       io->buf = (unsigned char *) p;
1747       io->size = new_size;
1748     } else {
1749       ok = 0;
1750       LOG(LL_ERROR,
1751           ("%lu->%lu", (unsigned long) io->size, (unsigned long) new_size));
1752     }
1753   }
1754   return ok;
1755 }
1756
1757 int mg_iobuf_init(struct mg_iobuf *io, size_t size) {
1758   return mg_iobuf_resize(io, size);
1759 }
1760
1761 size_t mg_iobuf_add(struct mg_iobuf *io, size_t ofs, const void *buf,
1762                     size_t len, size_t chunk_size) {
1763   size_t new_size = io->len + len;
1764   if (new_size > io->size) {
1765     new_size += chunk_size;             // Make sure that io->size
1766     new_size -= new_size % chunk_size;  // is aligned by chunk_size boundary
1767     mg_iobuf_resize(io, new_size);      // Attempt to realloc
1768     if (new_size != io->size) len = 0;  // Realloc failure, append nothing
1769   }
1770   if (ofs < io->len) memmove(io->buf + ofs + len, io->buf + ofs, io->len - ofs);
1771   if (buf != NULL) memmove(io->buf + ofs, buf, len);
1772   if (ofs > io->len) io->len += ofs - io->len;
1773   io->len += len;
1774   return len;
1775 }
1776
1777 size_t mg_iobuf_del(struct mg_iobuf *io, size_t ofs, size_t len) {
1778   if (ofs > io->len) ofs = io->len;
1779   if (ofs + len > io->len) len = io->len - ofs;
1780   memmove(io->buf + ofs, io->buf + ofs + len, io->len - ofs - len);
1781   zeromem(io->buf + io->len - len, len);
1782   io->len -= len;
1783   return len;
1784 }
1785
1786 void mg_iobuf_free(struct mg_iobuf *io) {
1787   mg_iobuf_resize(io, 0);
1788 }
1789
1790 #ifdef MG_ENABLE_LINES
1791 #line 1 "src/log.c"
1792 #endif
1793
1794
1795
1796 #if MG_ENABLE_LOG
1797 static void mg_log_stdout(const void *buf, size_t len, void *userdata) {
1798   (void) userdata;
1799   fwrite(buf, 1, len, stdout);
1800 }
1801
1802 static const char *s_spec = "2";
1803 static void (*s_fn)(const void *, size_t, void *) = mg_log_stdout;
1804 static void *s_fn_param = NULL;
1805
1806 void mg_log_set(const char *spec) {
1807   LOG(LL_DEBUG, ("Setting log level to %s", spec));
1808   s_spec = spec;
1809 }
1810
1811 bool mg_log_prefix(int level, const char *file, int line, const char *fname) {
1812   // static unsigned long seq;
1813   int max = LL_INFO;
1814   struct mg_str k, v, s = mg_str(s_spec);
1815   const char *p = strrchr(file, '/');
1816
1817   if (s_fn == NULL) return false;
1818
1819   if (p == NULL) p = strrchr(file, '\\');
1820   p = p == NULL ? file : p + 1;
1821
1822   while (mg_commalist(&s, &k, &v)) {
1823     if (v.len == 0) max = atoi(k.ptr);
1824     if (v.len > 0 && strncmp(p, k.ptr, k.len) == 0) max = atoi(v.ptr);
1825   }
1826
1827   if (level <= max) {
1828     char timebuf[21], buf[50] = "";
1829     time_t t = time(NULL);
1830     struct tm tmp, *tm = gmtime_r(&t, &tmp);
1831     int n;
1832     (void) tmp;
1833     strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", tm);
1834     n = snprintf(buf, sizeof(buf), "%s %d %s:%d:%s", timebuf, level, p, line,
1835                  fname);
1836     if (n < 0 || n > (int) sizeof(buf) - 2) n = sizeof(buf) - 2;
1837     while (n < (int) sizeof(buf) - 1) buf[n++] = ' ';
1838     s_fn(buf, sizeof(buf) - 1, s_fn_param);
1839     return true;
1840   } else {
1841     return false;
1842   }
1843 }
1844
1845 void mg_log(const char *fmt, ...) {
1846   char mem[256], *buf = mem;
1847   va_list ap;
1848   int len = 0;
1849   va_start(ap, fmt);
1850   len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
1851   va_end(ap);
1852   s_fn(buf, len > 0 ? (size_t) len : 0, s_fn_param);
1853   s_fn("\n", 1, s_fn_param);
1854   if (buf != mem) free(buf);
1855 }
1856
1857 void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *fnd) {
1858   s_fn = fn;
1859   s_fn_param = fnd;
1860 }
1861 #endif
1862
1863 #ifdef MG_ENABLE_LINES
1864 #line 1 "src/md5.c"
1865 #endif
1866 #include <string.h>
1867
1868
1869 #if defined(MG_ENABLE_MD5) && MG_ENABLE_MD5
1870 #if !defined(BYTE_ORDER) && defined(__BYTE_ORDER)
1871 #define BYTE_ORDER __BYTE_ORDER
1872 #ifndef LITTLE_ENDIAN
1873 #define LITTLE_ENDIAN __LITTLE_ENDIAN
1874 #endif /* LITTLE_ENDIAN */
1875 #ifndef BIG_ENDIAN
1876 #define BIG_ENDIAN __LITTLE_ENDIAN
1877 #endif /* BIG_ENDIAN */
1878 #endif /* BYTE_ORDER */
1879
1880 static void mg_byte_reverse(unsigned char *buf, unsigned longs) {
1881 /* Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN */
1882 #if BYTE_ORDER == BIG_ENDIAN
1883   do {
1884     uint32_t t = (uint32_t)((unsigned) buf[3] << 8 | buf[2]) << 16 |
1885                  ((unsigned) buf[1] << 8 | buf[0]);
1886     *(uint32_t *) buf = t;
1887     buf += 4;
1888   } while (--longs);
1889 #else
1890   (void) buf;
1891   (void) longs;
1892 #endif
1893 }
1894
1895 #define F1(x, y, z) (z ^ (x & (y ^ z)))
1896 #define F2(x, y, z) F1(z, x, y)
1897 #define F3(x, y, z) (x ^ y ^ z)
1898 #define F4(x, y, z) (y ^ (x | ~z))
1899
1900 #define MD5STEP(f, w, x, y, z, data, s) \
1901   (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
1902
1903 /*
1904  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
1905  * initialization constants.
1906  */
1907 void mg_md5_init(mg_md5_ctx *ctx) {
1908   ctx->buf[0] = 0x67452301;
1909   ctx->buf[1] = 0xefcdab89;
1910   ctx->buf[2] = 0x98badcfe;
1911   ctx->buf[3] = 0x10325476;
1912
1913   ctx->bits[0] = 0;
1914   ctx->bits[1] = 0;
1915 }
1916
1917 static void mg_md5_transform(uint32_t buf[4], uint32_t const in[16]) {
1918   uint32_t a, b, c, d;
1919
1920   a = buf[0];
1921   b = buf[1];
1922   c = buf[2];
1923   d = buf[3];
1924
1925   MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
1926   MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
1927   MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
1928   MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
1929   MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
1930   MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
1931   MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
1932   MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
1933   MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
1934   MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
1935   MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
1936   MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
1937   MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
1938   MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
1939   MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
1940   MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
1941
1942   MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
1943   MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
1944   MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
1945   MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
1946   MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
1947   MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
1948   MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
1949   MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
1950   MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
1951   MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
1952   MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
1953   MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
1954   MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
1955   MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
1956   MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
1957   MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
1958
1959   MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
1960   MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
1961   MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
1962   MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
1963   MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
1964   MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
1965   MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
1966   MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
1967   MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
1968   MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
1969   MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
1970   MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
1971   MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
1972   MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
1973   MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
1974   MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
1975
1976   MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
1977   MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
1978   MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
1979   MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
1980   MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
1981   MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
1982   MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
1983   MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
1984   MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
1985   MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
1986   MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
1987   MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
1988   MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
1989   MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
1990   MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
1991   MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
1992
1993   buf[0] += a;
1994   buf[1] += b;
1995   buf[2] += c;
1996   buf[3] += d;
1997 }
1998
1999 void mg_md5_update(mg_md5_ctx *ctx, const unsigned char *buf, size_t len) {
2000   uint32_t t;
2001
2002   t = ctx->bits[0];
2003   if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++;
2004   ctx->bits[1] += (uint32_t) len >> 29;
2005
2006   t = (t >> 3) & 0x3f;
2007
2008   if (t) {
2009     unsigned char *p = (unsigned char *) ctx->in + t;
2010
2011     t = 64 - t;
2012     if (len < t) {
2013       memcpy(p, buf, len);
2014       return;
2015     }
2016     memcpy(p, buf, t);
2017     mg_byte_reverse(ctx->in, 16);
2018     mg_md5_transform(ctx->buf, (uint32_t *) ctx->in);
2019     buf += t;
2020     len -= t;
2021   }
2022
2023   while (len >= 64) {
2024     memcpy(ctx->in, buf, 64);
2025     mg_byte_reverse(ctx->in, 16);
2026     mg_md5_transform(ctx->buf, (uint32_t *) ctx->in);
2027     buf += 64;
2028     len -= 64;
2029   }
2030
2031   memcpy(ctx->in, buf, len);
2032 }
2033
2034 void mg_md5_final(mg_md5_ctx *ctx, unsigned char digest[16]) {
2035   unsigned count;
2036   unsigned char *p;
2037   uint32_t *a;
2038
2039   count = (ctx->bits[0] >> 3) & 0x3F;
2040
2041   p = ctx->in + count;
2042   *p++ = 0x80;
2043   count = 64 - 1 - count;
2044   if (count < 8) {
2045     memset(p, 0, count);
2046     mg_byte_reverse(ctx->in, 16);
2047     mg_md5_transform(ctx->buf, (uint32_t *) ctx->in);
2048     memset(ctx->in, 0, 56);
2049   } else {
2050     memset(p, 0, count - 8);
2051   }
2052   mg_byte_reverse(ctx->in, 14);
2053
2054   a = (uint32_t *) ctx->in;
2055   a[14] = ctx->bits[0];
2056   a[15] = ctx->bits[1];
2057
2058   mg_md5_transform(ctx->buf, (uint32_t *) ctx->in);
2059   mg_byte_reverse((unsigned char *) ctx->buf, 4);
2060   memcpy(digest, ctx->buf, 16);
2061   memset((char *) ctx, 0, sizeof(*ctx));
2062 }
2063 #endif
2064
2065 #ifdef MG_ENABLE_LINES
2066 #line 1 "src/mqtt.c"
2067 #endif
2068
2069
2070
2071
2072
2073
2074
2075
2076 #define MQTT_CLEAN_SESSION 0x02
2077 #define MQTT_HAS_WILL 0x04
2078 #define MQTT_WILL_RETAIN 0x20
2079 #define MQTT_HAS_PASSWORD 0x40
2080 #define MQTT_HAS_USER_NAME 0x80
2081
2082 enum { MQTT_OK, MQTT_INCOMPLETE, MQTT_MALFORMED };
2083
2084 void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags,
2085                          uint32_t len) {
2086   uint8_t buf[1 + sizeof(len)], *vlen = &buf[1];
2087   buf[0] = (uint8_t) ((cmd << 4) | flags);
2088   do {
2089     *vlen = len % 0x80;
2090     len /= 0x80;
2091     if (len > 0) *vlen |= 0x80;
2092     vlen++;
2093   } while (len > 0 && vlen < &buf[sizeof(buf)]);
2094   mg_send(c, buf, (size_t) (vlen - buf));
2095 }
2096
2097 static void mg_send_u16(struct mg_connection *c, uint16_t value) {
2098   mg_send(c, &value, sizeof(value));
2099 }
2100
2101 void mg_mqtt_login(struct mg_connection *c, struct mg_mqtt_opts *opts) {
2102   char rnd[9], client_id[16];
2103   struct mg_str cid = opts->client_id;
2104   uint32_t total_len = 7 + 1 + 2 + 2;
2105   uint8_t connflag = (uint8_t) ((opts->qos & 3) << 1);
2106
2107   if (cid.len == 0) {
2108     mg_random(rnd, sizeof(rnd));
2109     mg_base64_encode((unsigned char *) rnd, sizeof(rnd), client_id);
2110     client_id[sizeof(client_id) - 1] = '\0';
2111     cid = mg_str(client_id);
2112   }
2113
2114   if (opts->user.len > 0) {
2115     total_len += 2 + (uint32_t) opts->user.len;
2116     connflag |= MQTT_HAS_USER_NAME;
2117   }
2118   if (opts->pass.len > 0) {
2119     total_len += 2 + (uint32_t) opts->pass.len;
2120     connflag |= MQTT_HAS_PASSWORD;
2121   }
2122   if (opts->will_topic.len > 0 && opts->will_message.len > 0) {
2123     total_len +=
2124         4 + (uint32_t) opts->will_topic.len + (uint32_t) opts->will_message.len;
2125     connflag |= MQTT_HAS_WILL;
2126   }
2127   if (opts->clean || cid.len == 0) connflag |= MQTT_CLEAN_SESSION;
2128   if (opts->will_retain) connflag |= MQTT_WILL_RETAIN;
2129   total_len += (uint32_t) cid.len;
2130
2131   mg_mqtt_send_header(c, MQTT_CMD_CONNECT, 0, total_len);
2132   mg_send(c, "\00\04MQTT\04", 7);
2133   mg_send(c, &connflag, sizeof(connflag));
2134   // keepalive == 0 means "do not disconnect us!"
2135   mg_send_u16(c, mg_htons((uint16_t) opts->keepalive));
2136   mg_send_u16(c, mg_htons((uint16_t) cid.len));
2137   mg_send(c, cid.ptr, cid.len);
2138   if (connflag & MQTT_HAS_WILL) {
2139     mg_send_u16(c, mg_htons((uint16_t) opts->will_topic.len));
2140     mg_send(c, opts->will_topic.ptr, opts->will_topic.len);
2141     mg_send_u16(c, mg_htons((uint16_t) opts->will_message.len));
2142     mg_send(c, opts->will_message.ptr, opts->will_message.len);
2143   }
2144   if (opts->user.len > 0) {
2145     mg_send_u16(c, mg_htons((uint16_t) opts->user.len));
2146     mg_send(c, opts->user.ptr, opts->user.len);
2147   }
2148   if (opts->pass.len > 0) {
2149     mg_send_u16(c, mg_htons((uint16_t) opts->pass.len));
2150     mg_send(c, opts->pass.ptr, opts->pass.len);
2151   }
2152 }
2153
2154 void mg_mqtt_pub(struct mg_connection *c, struct mg_str *topic,
2155                  struct mg_str *data, int qos, bool retain) {
2156   uint8_t flags = (uint8_t) (((qos & 3) << 1) | (retain ? 1 : 0));
2157   uint32_t total_len = 2 + (uint32_t) topic->len + (uint32_t) data->len;
2158   LOG(LL_DEBUG, ("%lu [%.*s] -> [%.*s]", c->id, (int) topic->len,
2159                  (char *) topic->ptr, (int) data->len, (char *) data->ptr));
2160   if (qos > 0) total_len += 2;
2161   mg_mqtt_send_header(c, MQTT_CMD_PUBLISH, flags, total_len);
2162   mg_send_u16(c, mg_htons((uint16_t) topic->len));
2163   mg_send(c, topic->ptr, topic->len);
2164   if (qos > 0) {
2165     static uint16_t s_id;
2166     if (++s_id == 0) s_id++;
2167     mg_send_u16(c, mg_htons(s_id));
2168   }
2169   mg_send(c, data->ptr, data->len);
2170 }
2171
2172 void mg_mqtt_sub(struct mg_connection *c, struct mg_str *topic, int qos) {
2173   static uint16_t s_id;
2174   uint8_t qos_ = qos & 3;
2175   uint32_t total_len = 2 + (uint32_t) topic->len + 2 + 1;
2176   mg_mqtt_send_header(c, MQTT_CMD_SUBSCRIBE, 2, total_len);
2177   if (++s_id == 0) ++s_id;
2178   mg_send_u16(c, mg_htons(s_id));
2179   mg_send_u16(c, mg_htons((uint16_t) topic->len));
2180   mg_send(c, topic->ptr, topic->len);
2181   mg_send(c, &qos_, sizeof(qos_));
2182 }
2183
2184 int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m) {
2185   uint8_t lc = 0, *p, *end;
2186   uint32_t n = 0, len_len = 0;
2187
2188   memset(m, 0, sizeof(*m));
2189   m->dgram.ptr = (char *) buf;
2190   if (len < 2) return MQTT_INCOMPLETE;
2191   m->cmd = (uint8_t) (buf[0] >> 4);
2192   m->qos = (buf[0] >> 1) & 3;
2193
2194   n = len_len = 0;
2195   p = (uint8_t *) buf + 1;
2196   while ((size_t) (p - buf) < len) {
2197     lc = *((uint8_t *) p++);
2198     n += (uint32_t) ((lc & 0x7f) << 7 * len_len);
2199     len_len++;
2200     if (!(lc & 0x80)) break;
2201     if (len_len >= 4) return MQTT_MALFORMED;
2202   }
2203   end = p + n;
2204   if (lc & 0x80 || end > buf + len) return MQTT_INCOMPLETE;
2205   m->dgram.len = (size_t) (end - buf);
2206
2207   switch (m->cmd) {
2208     case MQTT_CMD_CONNACK:
2209       if (end - p < 2) return MQTT_MALFORMED;
2210       m->ack = p[1];
2211       break;
2212     case MQTT_CMD_PUBACK:
2213     case MQTT_CMD_PUBREC:
2214     case MQTT_CMD_PUBREL:
2215     case MQTT_CMD_PUBCOMP:
2216     case MQTT_CMD_SUBACK:
2217       if (p + 2 > end) return MQTT_MALFORMED;
2218       m->id = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
2219       break;
2220     case MQTT_CMD_SUBSCRIBE: {
2221       if (p + 2 > end) return MQTT_MALFORMED;
2222       m->id = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
2223       p += 2;
2224       break;
2225     }
2226     case MQTT_CMD_PUBLISH: {
2227       if (p + 2 > end) return MQTT_MALFORMED;
2228       m->topic.len = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
2229       m->topic.ptr = (char *) p + 2;
2230       p += 2 + m->topic.len;
2231       if (p > end) return MQTT_MALFORMED;
2232       if (m->qos > 0) {
2233         if (p + 2 > end) return MQTT_MALFORMED;
2234         m->id = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
2235         p += 2;
2236       }
2237       if (p > end) return MQTT_MALFORMED;
2238       m->data.ptr = (char *) p;
2239       m->data.len = (size_t) (end - p);
2240       break;
2241     }
2242     default:
2243       break;
2244   }
2245   return MQTT_OK;
2246 }
2247
2248 static size_t mg_mqtt_next_topic(struct mg_mqtt_message *msg,
2249                                  struct mg_str *topic, uint8_t *qos,
2250                                  size_t pos) {
2251   unsigned char *buf = (unsigned char *) msg->dgram.ptr + pos;
2252   size_t new_pos;
2253   if (pos >= msg->dgram.len) return 0;
2254
2255   topic->len = (size_t) (((unsigned) buf[0]) << 8 | buf[1]);
2256   topic->ptr = (char *) buf + 2;
2257   new_pos = pos + 2 + topic->len + (qos == NULL ? 0 : 1);
2258   if ((size_t) new_pos > msg->dgram.len) return 0;
2259   if (qos != NULL) *qos = buf[2 + topic->len];
2260   return new_pos;
2261 }
2262
2263 size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
2264                         uint8_t *qos, size_t pos) {
2265   uint8_t tmp;
2266   return mg_mqtt_next_topic(msg, topic, qos == NULL ? &tmp : qos, pos);
2267 }
2268
2269 size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
2270                           size_t pos) {
2271   return mg_mqtt_next_topic(msg, topic, NULL, pos);
2272 }
2273
2274 static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data,
2275                     void *fn_data) {
2276   if (ev == MG_EV_READ) {
2277     for (;;) {
2278       struct mg_mqtt_message mm;
2279       int rc = mg_mqtt_parse(c->recv.buf, c->recv.len, &mm);
2280       if (rc == MQTT_MALFORMED) {
2281         LOG(LL_ERROR, ("%lu MQTT malformed message", c->id));
2282         c->is_closing = 1;
2283         break;
2284       } else if (rc == MQTT_OK) {
2285         LOG(LL_VERBOSE_DEBUG,
2286             ("%p MQTT CMD %d len %d [%.*s]", c->fd, mm.cmd, (int) mm.dgram.len,
2287              (int) mm.data.len, mm.data.ptr));
2288         switch (mm.cmd) {
2289           case MQTT_CMD_CONNACK:
2290             mg_call(c, MG_EV_MQTT_OPEN, &mm.ack);
2291             if (mm.ack == 0) {
2292               LOG(LL_INFO, ("%lu Connected", c->id));
2293             } else {
2294               LOG(LL_ERROR, ("%lu MQTT auth failed, code %d", c->id, mm.ack));
2295               c->is_closing = 1;
2296             }
2297             break;
2298           case MQTT_CMD_PUBLISH: {
2299             LOG(LL_DEBUG, ("%lu [%.*s] -> [%.*s]", c->id, (int) mm.topic.len,
2300                            mm.topic.ptr, (int) mm.data.len, mm.data.ptr));
2301             mg_call(c, MG_EV_MQTT_MSG, &mm);
2302             break;
2303           }
2304         }
2305         mg_call(c, MG_EV_MQTT_CMD, &mm);
2306         mg_iobuf_del(&c->recv, 0, mm.dgram.len);
2307       } else {
2308         break;
2309       }
2310     }
2311   }
2312   (void) ev_data;
2313   (void) fn_data;
2314 }
2315
2316 void mg_mqtt_ping(struct mg_connection *nc) {
2317   mg_mqtt_send_header(nc, MQTT_CMD_PINGREQ, 0, 0);
2318 }
2319
2320 void mg_mqtt_pong(struct mg_connection *nc) {
2321   mg_mqtt_send_header(nc, MQTT_CMD_PINGRESP, 0, 0);
2322 }
2323
2324 void mg_mqtt_disconnect(struct mg_connection *nc) {
2325   mg_mqtt_send_header(nc, MQTT_CMD_DISCONNECT, 0, 0);
2326 }
2327
2328 struct mg_connection *mg_mqtt_connect(struct mg_mgr *mgr, const char *url,
2329                                       struct mg_mqtt_opts *opts,
2330                                       mg_event_handler_t fn, void *fn_data) {
2331   struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
2332   if (c != NULL) {
2333     struct mg_mqtt_opts empty;
2334     memset(&empty, 0, sizeof(empty));
2335     mg_mqtt_login(c, opts == NULL ? &empty : opts);
2336     c->pfn = mqtt_cb;
2337   }
2338   return c;
2339 }
2340
2341 struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
2342                                      mg_event_handler_t fn, void *fn_data) {
2343   struct mg_connection *c = mg_listen(mgr, url, fn, fn_data);
2344   if (c != NULL) c->pfn = mqtt_cb, c->pfn_data = mgr;
2345   return c;
2346 }
2347
2348 #ifdef MG_ENABLE_LINES
2349 #line 1 "src/net.c"
2350 #endif
2351
2352
2353
2354
2355 int mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) {
2356   char mem[256], *buf = mem;
2357   int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
2358   len = mg_send(c, buf, len > 0 ? (size_t) len : 0);
2359   if (buf != mem) free(buf);
2360   return len;
2361 }
2362
2363 int mg_printf(struct mg_connection *c, const char *fmt, ...) {
2364   int len = 0;
2365   va_list ap;
2366   va_start(ap, fmt);
2367   len = mg_vprintf(c, fmt, ap);
2368   va_end(ap);
2369   return len;
2370 }
2371
2372 char *mg_straddr(struct mg_connection *c, char *buf, size_t len) {
2373   char tmp[100];
2374   const char *fmt = c->peer.is_ip6 ? "[%s]:%d" : "%s:%d";
2375   mg_ntoa(&c->peer, tmp, sizeof(tmp));
2376   snprintf(buf, len, fmt, tmp, (int) mg_ntohs(c->peer.port));
2377   return buf;
2378 }
2379
2380 char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len) {
2381   if (addr->is_ip6) {
2382     uint16_t *p = (uint16_t *) addr->ip6;
2383     snprintf(buf, len, "%x:%x:%x:%x:%x:%x:%x:%x", mg_htons(p[0]),
2384              mg_htons(p[1]), mg_htons(p[2]), mg_htons(p[3]), mg_htons(p[4]),
2385              mg_htons(p[5]), mg_htons(p[6]), mg_htons(p[7]));
2386   } else {
2387     uint8_t p[4];
2388     memcpy(p, &addr->ip, sizeof(p));
2389     snprintf(buf, len, "%d.%d.%d.%d", (int) p[0], (int) p[1], (int) p[2],
2390              (int) p[3]);
2391   }
2392   return buf;
2393 }
2394
2395 static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
2396   if (mg_vcasecmp(&str, "localhost") != 0) return false;
2397   addr->ip = mg_htonl(0x7f000001);
2398   addr->is_ip6 = false;
2399   return true;
2400 }
2401
2402 static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
2403   if (str.len > 0) return false;
2404   addr->ip = 0;
2405   addr->is_ip6 = false;
2406   return true;
2407 }
2408
2409 static bool mg_aton4(struct mg_str str, struct mg_addr *addr) {
2410   uint8_t data[4] = {0, 0, 0, 0};
2411   size_t i, num_dots = 0;
2412   for (i = 0; i < str.len; i++) {
2413     if (str.ptr[i] >= '0' && str.ptr[i] <= '9') {
2414       int octet = data[num_dots] * 10 + (str.ptr[i] - '0');
2415       if (octet > 255) return false;
2416       data[num_dots] = (uint8_t) octet;
2417     } else if (str.ptr[i] == '.') {
2418       if (num_dots >= 3 || i == 0 || str.ptr[i - 1] == '.') return false;
2419       num_dots++;
2420     } else {
2421       return false;
2422     }
2423   }
2424   if (num_dots != 3 || str.ptr[i - 1] == '.') return false;
2425   memcpy(&addr->ip, data, sizeof(data));
2426   addr->is_ip6 = false;
2427   return true;
2428 }
2429
2430 static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) {
2431   int i;
2432   if (str.len < 14) return false;
2433   if (str.ptr[0] != ':' || str.ptr[1] != ':' || str.ptr[6] != ':') return false;
2434   for (i = 2; i < 6; i++) {
2435     if (str.ptr[i] != 'f' && str.ptr[i] != 'F') return false;
2436   }
2437   if (!mg_aton4(mg_str_n(&str.ptr[7], str.len - 7), addr)) return false;
2438   memset(addr->ip6, 0, sizeof(addr->ip6));
2439   addr->ip6[10] = addr->ip6[11] = 255;
2440   memcpy(&addr->ip6[12], &addr->ip, 4);
2441   addr->is_ip6 = true;
2442   return true;
2443 }
2444
2445 static bool mg_aton6(struct mg_str str, struct mg_addr *addr) {
2446   size_t i, j = 0, n = 0, dc = 42;
2447   if (str.len > 2 && str.ptr[0] == '[') str.ptr++, str.len -= 2;
2448   if (mg_v4mapped(str, addr)) return true;
2449   for (i = 0; i < str.len; i++) {
2450     if ((str.ptr[i] >= '0' && str.ptr[i] <= '9') ||
2451         (str.ptr[i] >= 'a' && str.ptr[i] <= 'f') ||
2452         (str.ptr[i] >= 'A' && str.ptr[i] <= 'F')) {
2453       unsigned long val;
2454       if (i > j + 3) return false;
2455       // LOG(LL_DEBUG, ("%zu %zu [%.*s]", i, j, (int) (i - j + 1),
2456       // &str.ptr[j]));
2457       val = mg_unhexn(&str.ptr[j], i - j + 1);
2458       addr->ip6[n] = (uint8_t) ((val >> 8) & 255);
2459       addr->ip6[n + 1] = (uint8_t) (val & 255);
2460     } else if (str.ptr[i] == ':') {
2461       j = i + 1;
2462       if (i > 0 && str.ptr[i - 1] == ':') {
2463         dc = n;  // Double colon
2464         if (i > 1 && str.ptr[i - 2] == ':') return false;
2465       } else if (i > 0) {
2466         n += 2;
2467       }
2468       if (n > 14) return false;
2469       addr->ip6[n] = addr->ip6[n + 1] = 0;  // For trailing ::
2470     } else {
2471       return false;
2472     }
2473   }
2474   if (n < 14 && dc == 42) return false;
2475   if (n < 14) {
2476     memmove(&addr->ip6[dc + (14 - n)], &addr->ip6[dc], n - dc + 2);
2477     memset(&addr->ip6[dc], 0, 14 - n);
2478   }
2479   addr->is_ip6 = true;
2480   return true;
2481 }
2482
2483 bool mg_aton(struct mg_str str, struct mg_addr *addr) {
2484   // LOG(LL_INFO, ("[%.*s]", (int) str.len, str.ptr));
2485   return mg_atone(str, addr) || mg_atonl(str, addr) || mg_aton4(str, addr) ||
2486          mg_aton6(str, addr);
2487 }
2488
2489 void mg_mgr_free(struct mg_mgr *mgr) {
2490   struct mg_connection *c;
2491   for (c = mgr->conns; c != NULL; c = c->next) c->is_closing = 1;
2492   mg_mgr_poll(mgr, 0);
2493 #if MG_ARCH == MG_ARCH_FREERTOS_TCP
2494   FreeRTOS_DeleteSocketSet(mgr->ss);
2495 #endif
2496   LOG(LL_INFO, ("All connections closed"));
2497 }
2498
2499 void mg_mgr_init(struct mg_mgr *mgr) {
2500   memset(mgr, 0, sizeof(*mgr));
2501 #if defined(_WIN32) && MG_ENABLE_WINSOCK
2502   // clang-format off
2503   { WSADATA data; WSAStartup(MAKEWORD(2, 2), &data); }
2504   // clang-format on
2505 #elif MG_ARCH == MG_ARCH_FREERTOS_TCP
2506   mgr->ss = FreeRTOS_CreateSocketSet();
2507 #elif defined(__unix) || defined(__unix__) || defined(__APPLE__)
2508   // Ignore SIGPIPE signal, so if client cancels the request, it
2509   // won't kill the whole process.
2510   signal(SIGPIPE, SIG_IGN);
2511 #endif
2512   mgr->dnstimeout = 3000;
2513   mgr->dns4.url = "udp://8.8.8.8:53";
2514   mgr->dns6.url = "udp://[2001:4860:4860::8888]:53";
2515 }
2516
2517 #ifdef MG_ENABLE_LINES
2518 #line 1 "src/sha1.c"
2519 #endif
2520 /* Copyright(c) By Steve Reid <steve@edmweb.com> */
2521 /* 100% Public Domain */
2522
2523 #include <string.h>
2524
2525 /*
2526  * clang with std=-c99 uses __LITTLE_ENDIAN, by default
2527  * while for ex, RTOS gcc - LITTLE_ENDIAN, by default
2528  * it depends on __USE_BSD, but let's have everything
2529  */
2530 #if !defined(BYTE_ORDER) && defined(__BYTE_ORDER)
2531 #define BYTE_ORDER __BYTE_ORDER
2532 #ifndef LITTLE_ENDIAN
2533 #define LITTLE_ENDIAN __LITTLE_ENDIAN
2534 #endif /* LITTLE_ENDIAN */
2535 #ifndef BIG_ENDIAN
2536 #define BIG_ENDIAN __LITTLE_ENDIAN
2537 #endif /* BIG_ENDIAN */
2538 #endif /* BYTE_ORDER */
2539
2540 union char64long16 {
2541   unsigned char c[64];
2542   uint32_t l[16];
2543 };
2544
2545 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
2546
2547 static uint32_t blk0(union char64long16 *block, int i) {
2548 /* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
2549 #if BYTE_ORDER == LITTLE_ENDIAN
2550   block->l[i] =
2551       (rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF);
2552 #endif
2553   return block->l[i];
2554 }
2555
2556 /* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */
2557 #undef blk
2558 #undef R0
2559 #undef R1
2560 #undef R2
2561 #undef R3
2562 #undef R4
2563
2564 #define blk(i)                                                               \
2565   (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
2566                               block->l[(i + 2) & 15] ^ block->l[i & 15],     \
2567                           1))
2568 #define R0(v, w, x, y, z, i)                                          \
2569   z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
2570   w = rol(w, 30);
2571 #define R1(v, w, x, y, z, i)                                  \
2572   z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
2573   w = rol(w, 30);
2574 #define R2(v, w, x, y, z, i)                          \
2575   z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
2576   w = rol(w, 30);
2577 #define R3(v, w, x, y, z, i)                                        \
2578   z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
2579   w = rol(w, 30);
2580 #define R4(v, w, x, y, z, i)                          \
2581   z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
2582   w = rol(w, 30);
2583
2584 static void mg_sha1_transform(uint32_t state[5], const unsigned char buffer[64]) {
2585   uint32_t a, b, c, d, e;
2586   union char64long16 block[1];
2587
2588   memcpy(block, buffer, 64);
2589   a = state[0];
2590   b = state[1];
2591   c = state[2];
2592   d = state[3];
2593   e = state[4];
2594   R0(a, b, c, d, e, 0);
2595   R0(e, a, b, c, d, 1);
2596   R0(d, e, a, b, c, 2);
2597   R0(c, d, e, a, b, 3);
2598   R0(b, c, d, e, a, 4);
2599   R0(a, b, c, d, e, 5);
2600   R0(e, a, b, c, d, 6);
2601   R0(d, e, a, b, c, 7);
2602   R0(c, d, e, a, b, 8);
2603   R0(b, c, d, e, a, 9);
2604   R0(a, b, c, d, e, 10);
2605   R0(e, a, b, c, d, 11);
2606   R0(d, e, a, b, c, 12);
2607   R0(c, d, e, a, b, 13);
2608   R0(b, c, d, e, a, 14);
2609   R0(a, b, c, d, e, 15);
2610   R1(e, a, b, c, d, 16);
2611   R1(d, e, a, b, c, 17);
2612   R1(c, d, e, a, b, 18);
2613   R1(b, c, d, e, a, 19);
2614   R2(a, b, c, d, e, 20);
2615   R2(e, a, b, c, d, 21);
2616   R2(d, e, a, b, c, 22);
2617   R2(c, d, e, a, b, 23);
2618   R2(b, c, d, e, a, 24);
2619   R2(a, b, c, d, e, 25);
2620   R2(e, a, b, c, d, 26);
2621   R2(d, e, a, b, c, 27);
2622   R2(c, d, e, a, b, 28);
2623   R2(b, c, d, e, a, 29);
2624   R2(a, b, c, d, e, 30);
2625   R2(e, a, b, c, d, 31);
2626   R2(d, e, a, b, c, 32);
2627   R2(c, d, e, a, b, 33);
2628   R2(b, c, d, e, a, 34);
2629   R2(a, b, c, d, e, 35);
2630   R2(e, a, b, c, d, 36);
2631   R2(d, e, a, b, c, 37);
2632   R2(c, d, e, a, b, 38);
2633   R2(b, c, d, e, a, 39);
2634   R3(a, b, c, d, e, 40);
2635   R3(e, a, b, c, d, 41);
2636   R3(d, e, a, b, c, 42);
2637   R3(c, d, e, a, b, 43);
2638   R3(b, c, d, e, a, 44);
2639   R3(a, b, c, d, e, 45);
2640   R3(e, a, b, c, d, 46);
2641   R3(d, e, a, b, c, 47);
2642   R3(c, d, e, a, b, 48);
2643   R3(b, c, d, e, a, 49);
2644   R3(a, b, c, d, e, 50);
2645   R3(e, a, b, c, d, 51);
2646   R3(d, e, a, b, c, 52);
2647   R3(c, d, e, a, b, 53);
2648   R3(b, c, d, e, a, 54);
2649   R3(a, b, c, d, e, 55);
2650   R3(e, a, b, c, d, 56);
2651   R3(d, e, a, b, c, 57);
2652   R3(c, d, e, a, b, 58);
2653   R3(b, c, d, e, a, 59);
2654   R4(a, b, c, d, e, 60);
2655   R4(e, a, b, c, d, 61);
2656   R4(d, e, a, b, c, 62);
2657   R4(c, d, e, a, b, 63);
2658   R4(b, c, d, e, a, 64);
2659   R4(a, b, c, d, e, 65);
2660   R4(e, a, b, c, d, 66);
2661   R4(d, e, a, b, c, 67);
2662   R4(c, d, e, a, b, 68);
2663   R4(b, c, d, e, a, 69);
2664   R4(a, b, c, d, e, 70);
2665   R4(e, a, b, c, d, 71);
2666   R4(d, e, a, b, c, 72);
2667   R4(c, d, e, a, b, 73);
2668   R4(b, c, d, e, a, 74);
2669   R4(a, b, c, d, e, 75);
2670   R4(e, a, b, c, d, 76);
2671   R4(d, e, a, b, c, 77);
2672   R4(c, d, e, a, b, 78);
2673   R4(b, c, d, e, a, 79);
2674   state[0] += a;
2675   state[1] += b;
2676   state[2] += c;
2677   state[3] += d;
2678   state[4] += e;
2679   /* Erase working structures. The order of operations is important,
2680    * used to ensure that compiler doesn't optimize those out. */
2681   memset(block, 0, sizeof(block));
2682   a = b = c = d = e = 0;
2683   (void) a;
2684   (void) b;
2685   (void) c;
2686   (void) d;
2687   (void) e;
2688 }
2689
2690 void mg_sha1_init(mg_sha1_ctx *context) {
2691   context->state[0] = 0x67452301;
2692   context->state[1] = 0xEFCDAB89;
2693   context->state[2] = 0x98BADCFE;
2694   context->state[3] = 0x10325476;
2695   context->state[4] = 0xC3D2E1F0;
2696   context->count[0] = context->count[1] = 0;
2697 }
2698
2699 void mg_sha1_update(mg_sha1_ctx *context, const unsigned char *data,
2700                     size_t len) {
2701   size_t i, j;
2702
2703   j = context->count[0];
2704   if ((context->count[0] += (uint32_t) len << 3) < j) context->count[1]++;
2705   context->count[1] += (uint32_t)(len >> 29);
2706   j = (j >> 3) & 63;
2707   if ((j + len) > 63) {
2708     memcpy(&context->buffer[j], data, (i = 64 - j));
2709     mg_sha1_transform(context->state, context->buffer);
2710     for (; i + 63 < len; i += 64) {
2711       mg_sha1_transform(context->state, &data[i]);
2712     }
2713     j = 0;
2714   } else
2715     i = 0;
2716   memcpy(&context->buffer[j], &data[i], len - i);
2717 }
2718
2719 void mg_sha1_final(unsigned char digest[20], mg_sha1_ctx *context) {
2720   unsigned i;
2721   unsigned char finalcount[8], c;
2722
2723   for (i = 0; i < 8; i++) {
2724     finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >>
2725                                       ((3 - (i & 3)) * 8)) &
2726                                      255);
2727   }
2728   c = 0200;
2729   mg_sha1_update(context, &c, 1);
2730   while ((context->count[0] & 504) != 448) {
2731     c = 0000;
2732     mg_sha1_update(context, &c, 1);
2733   }
2734   mg_sha1_update(context, finalcount, 8);
2735   for (i = 0; i < 20; i++) {
2736     digest[i] =
2737         (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
2738   }
2739   memset(context, '\0', sizeof(*context));
2740   memset(&finalcount, '\0', sizeof(finalcount));
2741 }
2742
2743 void mg_hmac_sha1(const unsigned char *key, size_t keylen,
2744                   const unsigned char *data, size_t datalen,
2745                   unsigned char out[20]) {
2746   mg_sha1_ctx ctx;
2747   unsigned char buf1[64], buf2[64], tmp_key[20], i;
2748
2749   if (keylen > sizeof(buf1)) {
2750     mg_sha1_init(&ctx);
2751     mg_sha1_update(&ctx, key, keylen);
2752     mg_sha1_final(tmp_key, &ctx);
2753     key = tmp_key;
2754     keylen = sizeof(tmp_key);
2755   }
2756
2757   memset(buf1, 0, sizeof(buf1));
2758   memset(buf2, 0, sizeof(buf2));
2759   memcpy(buf1, key, keylen);
2760   memcpy(buf2, key, keylen);
2761
2762   for (i = 0; i < sizeof(buf1); i++) {
2763     buf1[i] ^= 0x36;
2764     buf2[i] ^= 0x5c;
2765   }
2766
2767   mg_sha1_init(&ctx);
2768   mg_sha1_update(&ctx, buf1, sizeof(buf1));
2769   mg_sha1_update(&ctx, data, datalen);
2770   mg_sha1_final(out, &ctx);
2771
2772   mg_sha1_init(&ctx);
2773   mg_sha1_update(&ctx, buf2, sizeof(buf2));
2774   mg_sha1_update(&ctx, out, 20);
2775   mg_sha1_final(out, &ctx);
2776 }
2777
2778 #ifdef MG_ENABLE_LINES
2779 #line 1 "src/sntp.c"
2780 #endif
2781
2782
2783
2784
2785
2786
2787 #define SNTP_INTERVAL_SEC (3600)
2788 #define SNTP_TIME_OFFSET 2208988800UL
2789
2790 static unsigned long s_sntmp_next;
2791
2792 int mg_sntp_parse(const unsigned char *buf, size_t len, struct timeval *tv) {
2793   int mode = len > 0 ? buf[0] & 7 : 0, res = -1;
2794   if (len < 48) {
2795     LOG(LL_ERROR, ("%s", "corrupt packet"));
2796   } else if ((buf[0] & 0x38) >> 3 != 4) {
2797     LOG(LL_ERROR, ("%s", "wrong version"));
2798   } else if (mode != 4 && mode != 5) {
2799     LOG(LL_ERROR, ("%s", "not a server reply"));
2800   } else if (buf[1] == 0) {
2801     LOG(LL_ERROR, ("%s", "server sent a kiss of death"));
2802   } else {
2803     uint32_t *data = (uint32_t *) &buf[40];
2804     tv->tv_sec = (time_t) (mg_ntohl(data[0]) - SNTP_TIME_OFFSET);
2805     tv->tv_usec = (suseconds_t) mg_ntohl(data[1]);
2806     s_sntmp_next = (unsigned long) (tv->tv_sec + SNTP_INTERVAL_SEC);
2807     res = 0;
2808   }
2809   return res;
2810 }
2811
2812 static void sntp_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
2813   if (ev == MG_EV_READ) {
2814     struct timeval tv = {0, 0};
2815     if (mg_sntp_parse(c->recv.buf, c->recv.len, &tv) == 0) {
2816       mg_call(c, MG_EV_SNTP_TIME, &tv);
2817       LOG(LL_DEBUG, ("%u.%u, next at %lu", (unsigned) tv.tv_sec,
2818                      (unsigned) tv.tv_usec, s_sntmp_next));
2819     }
2820     c->recv.len = 0;  // Clear receive buffer
2821   } else if (ev == MG_EV_CONNECT) {
2822     mg_sntp_send(c, (unsigned long) time(NULL));
2823   } else if (ev == MG_EV_CLOSE) {
2824   }
2825   (void) fnd;
2826   (void) evd;
2827 }
2828
2829 void mg_sntp_send(struct mg_connection *c, unsigned long utc) {
2830   if (c->is_resolving) {
2831     LOG(LL_ERROR, ("%lu wait until resolved", c->id));
2832   } else if (utc > s_sntmp_next) {
2833     uint8_t buf[48] = {0};
2834     s_sntmp_next = utc + SNTP_INTERVAL_SEC;
2835     buf[0] = (0 << 6) | (4 << 3) | 3;
2836     mg_send(c, buf, sizeof(buf));
2837     LOG(LL_DEBUG, ("%lu ct %lu, next at %lu", c->id, utc, s_sntmp_next));
2838   }
2839 }
2840
2841 struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url,
2842                                       mg_event_handler_t fn, void *fnd) {
2843   struct mg_connection *c = NULL;
2844   if (url == NULL) url = "udp://time.google.com:123";
2845   if ((c = mg_connect(mgr, url, fn, fnd)) != NULL) c->pfn = sntp_cb;
2846   return c;
2847 }
2848
2849 #ifdef MG_ENABLE_LINES
2850 #line 1 "src/sock.c"
2851 #endif
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862 #if MG_ENABLE_SOCKET
2863 #if defined(_WIN32) && MG_ENABLE_WINSOCK
2864 #define MG_SOCK_ERRNO WSAGetLastError()
2865 #ifndef SO_EXCLUSIVEADDRUSE
2866 #define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR))
2867 #endif
2868 #elif MG_ARCH == MG_ARCH_FREERTOS_TCP
2869 #define MG_SOCK_ERRNO errno
2870 typedef Socket_t SOCKET;
2871 #define INVALID_SOCKET FREERTOS_INVALID_SOCKET
2872 #else
2873 #define MG_SOCK_ERRNO errno
2874 #ifndef closesocket
2875 #define closesocket(x) close(x)
2876 #endif
2877 #define INVALID_SOCKET (-1)
2878 typedef int SOCKET;
2879 #endif
2880
2881 #define FD(c_) ((SOCKET) (size_t) (c_)->fd)
2882 #define S2PTR(s_) ((void *) (size_t) (s_))
2883
2884 #ifndef MSG_NONBLOCKING
2885 #define MSG_NONBLOCKING 0
2886 #endif
2887
2888 #ifndef AF_INET6
2889 #define AF_INET6 10
2890 #endif
2891
2892 union usa {
2893   struct sockaddr sa;
2894   struct sockaddr_in sin;
2895 #if MG_ENABLE_IPV6
2896   struct sockaddr_in6 sin6;
2897 #endif
2898 };
2899
2900 static socklen_t tousa(struct mg_addr *a, union usa *usa) {
2901   socklen_t len = sizeof(usa->sin);
2902   memset(usa, 0, sizeof(*usa));
2903   usa->sin.sin_family = AF_INET;
2904   usa->sin.sin_port = a->port;
2905   *(uint32_t *) &usa->sin.sin_addr = a->ip;
2906 #if MG_ENABLE_IPV6
2907   if (a->is_ip6) {
2908     usa->sin.sin_family = AF_INET6;
2909     usa->sin6.sin6_port = a->port;
2910     memcpy(&usa->sin6.sin6_addr, a->ip6, sizeof(a->ip6));
2911     len = sizeof(usa->sin6);
2912   }
2913 #endif
2914   return len;
2915 }
2916
2917 static void tomgaddr(union usa *usa, struct mg_addr *a, bool is_ip6) {
2918   a->is_ip6 = is_ip6;
2919   a->port = usa->sin.sin_port;
2920   memcpy(&a->ip, &usa->sin.sin_addr, sizeof(a->ip));
2921 #if MG_ENABLE_IPV6
2922   if (is_ip6) {
2923     memcpy(a->ip6, &usa->sin6.sin6_addr, sizeof(a->ip6));
2924     a->port = usa->sin6.sin6_port;
2925   }
2926 #endif
2927 }
2928
2929 static bool mg_sock_would_block(void) {
2930   int err = MG_SOCK_ERRNO;
2931   return err == EINPROGRESS || err == EWOULDBLOCK
2932 #ifndef WINCE
2933          || err == EAGAIN || err == EINTR
2934 #endif
2935 #if defined(_WIN32) && MG_ENABLE_WINSOCK
2936          || err == WSAEINTR || err == WSAEWOULDBLOCK
2937 #endif
2938       ;
2939 }
2940
2941 static struct mg_connection *alloc_conn(struct mg_mgr *mgr, bool is_client,
2942                                         SOCKET fd) {
2943   struct mg_connection *c = (struct mg_connection *) calloc(1, sizeof(*c));
2944   if (c != NULL) {
2945     c->is_client = is_client;
2946     c->fd = S2PTR(fd);
2947     c->mgr = mgr;
2948     c->id = ++mgr->nextid;
2949   }
2950   return c;
2951 }
2952
2953 static long mg_sock_send(struct mg_connection *c, const void *buf, size_t len) {
2954   long n;
2955 #if !defined(__APPLE__)
2956   // See #1338, #1382. On Windows, UDP send() can fail despite connected.
2957   // Use sendto() instead. But not on Mac - we'll get EISCONN
2958   if (c->is_udp) {
2959     union usa usa;
2960     socklen_t slen = tousa(&c->peer, &usa);
2961     n = sendto(FD(c), (char *) buf, len, 0, &usa.sa, slen);
2962   } else
2963 #endif
2964   {
2965     n = send(FD(c), (char *) buf, len, MSG_NONBLOCKING);
2966   }
2967   return n == 0 ? -1 : n < 0 && mg_sock_would_block() ? 0 : n;
2968 }
2969
2970 bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
2971   return c->is_udp ? mg_sock_send(c, buf, len) > 0
2972                    : mg_iobuf_add(&c->send, c->send.len, buf, len, MG_IO_SIZE);
2973 }
2974
2975 static void mg_set_non_blocking_mode(SOCKET fd) {
2976 #if defined(_WIN32) && MG_ENABLE_WINSOCK
2977   unsigned long on = 1;
2978   ioctlsocket(fd, FIONBIO, &on);
2979 #elif MG_ARCH == MG_ARCH_FREERTOS_TCP
2980   const BaseType_t off = 0;
2981   setsockopt(fd, 0, FREERTOS_SO_RCVTIMEO, &off, sizeof(off));
2982   setsockopt(fd, 0, FREERTOS_SO_SNDTIMEO, &off, sizeof(off));
2983 #elif MG_ARCH == MG_ARCH_FREERTOS_LWIP
2984   lwip_fcntl(fd, F_SETFL, O_NONBLOCK);
2985 #elif MG_ARCH == MG_ARCH_AZURERTOS
2986   fcntl(fd, F_SETFL, O_NONBLOCK);
2987 #else
2988   fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);  // Set non-blocking mode
2989   fcntl(fd, F_SETFD, FD_CLOEXEC);                       // Set close-on-exec
2990 #endif
2991 }
2992
2993 static SOCKET mg_open_listener(const char *url, struct mg_addr *addr) {
2994   SOCKET fd = INVALID_SOCKET;
2995   int s_err = 0;  // Memoized socket error, in case closesocket() overrides it
2996   memset(addr, 0, sizeof(*addr));
2997   addr->port = mg_htons(mg_url_port(url));
2998   if (!mg_aton(mg_url_host(url), addr)) {
2999     LOG(LL_ERROR, ("invalid listening URL: %s", url));
3000   } else {
3001     union usa usa;
3002     socklen_t slen = tousa(addr, &usa);
3003     int on = 1, af = addr->is_ip6 ? AF_INET6 : AF_INET;
3004     int type = strncmp(url, "udp:", 4) == 0 ? SOCK_DGRAM : SOCK_STREAM;
3005     int proto = type == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
3006     (void) on;
3007
3008     if ((fd = socket(af, type, proto)) != INVALID_SOCKET &&
3009 #if (!defined(_WIN32) || !defined(SO_EXCLUSIVEADDRUSE)) && \
3010     (!defined(LWIP_SOCKET) || (defined(LWIP_SOCKET) && SO_REUSE == 1))
3011         // 1. SO_RESUSEADDR is not enabled on Windows because the semantics of
3012         //    SO_REUSEADDR on UNIX and Windows is different. On Windows,
3013         //    SO_REUSEADDR allows to bind a socket to a port without error even
3014         //    if the port is already open by another program. This is not the
3015         //    behavior SO_REUSEADDR was designed for, and leads to hard-to-track
3016         //    failure scenarios. Therefore, SO_REUSEADDR was disabled on Windows
3017         //    unless SO_EXCLUSIVEADDRUSE is supported and set on a socket.
3018         // 2. In case of LWIP, SO_REUSEADDR should be explicitly enabled, by
3019         // defining
3020         //    SO_REUSE (in lwipopts.h), otherwise the code below will compile
3021         //    but won't work! (setsockopt will return EINVAL)
3022         !setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) &&
3023 #endif
3024 #if defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE) && !defined(WINCE)
3025         // "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE"
3026         //! setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof(on))
3027         //! &&
3028         !setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &on,
3029                     sizeof(on)) &&
3030 #endif
3031         bind(fd, &usa.sa, slen) == 0 &&
3032         // NOTE(lsm): FreeRTOS uses backlog value as a connection limit
3033         (type == SOCK_DGRAM || listen(fd, MG_SOCK_LISTEN_BACKLOG_SIZE) == 0)) {
3034       // In case port was set to 0, get the real port number
3035       if (getsockname(fd, &usa.sa, &slen) == 0) {
3036         addr->port = usa.sin.sin_port;
3037 #if MG_ENABLE_IPV6
3038         if (addr->is_ip6) addr->port = usa.sin6.sin6_port;
3039 #endif
3040       }
3041       mg_set_non_blocking_mode(fd);
3042     } else if (fd != INVALID_SOCKET) {
3043       s_err = MG_SOCK_ERRNO;
3044       closesocket(fd);
3045       fd = INVALID_SOCKET;
3046     }
3047   }
3048   if (fd == INVALID_SOCKET) {
3049     if (s_err == 0) s_err = MG_SOCK_ERRNO;
3050     LOG(LL_ERROR, ("Failed to listen on %s, errno %d", url, s_err));
3051   }
3052
3053   return fd;
3054 }
3055
3056 static long mg_sock_recv(struct mg_connection *c, void *buf, size_t len) {
3057   long n = 0;
3058   if (c->is_udp) {
3059     union usa usa;
3060     socklen_t slen = tousa(&c->peer, &usa);
3061     n = recvfrom(FD(c), (char *) buf, len, 0, &usa.sa, &slen);
3062     if (n > 0) tomgaddr(&usa, &c->peer, slen != sizeof(usa.sin));
3063   } else {
3064     n = recv(FD(c), (char *) buf, len, MSG_NONBLOCKING);
3065   }
3066   return n == 0 ? -1 : n < 0 && mg_sock_would_block() ? 0 : n;
3067 }
3068
3069 // NOTE(lsm): do only one iteration of reads, cause some systems
3070 // (e.g. FreeRTOS stack) return 0 instead of -1/EWOULDBLOCK when no data
3071 static long read_conn(struct mg_connection *c) {
3072   long n = -1;
3073   if (c->recv.len >= MG_MAX_RECV_BUF_SIZE) {
3074     mg_error(c, "max_recv_buf_size reached");
3075   } else if (c->recv.size - c->recv.len < MG_IO_SIZE &&
3076              !mg_iobuf_resize(&c->recv, c->recv.size + MG_IO_SIZE)) {
3077     mg_error(c, "oom");
3078   } else {
3079     char *buf = (char *) &c->recv.buf[c->recv.len];
3080     size_t len = c->recv.size - c->recv.len;
3081     n = c->is_tls ? mg_tls_recv(c, buf, len) : mg_sock_recv(c, buf, len);
3082     LOG(n > 0 ? LL_VERBOSE_DEBUG : LL_DEBUG,
3083         ("%-3lu %d%d%d%d%d%d%d%d%d%d%d%d%d%d %7ld %ld/%ld err %d", c->id,
3084          c->is_listening, c->is_client, c->is_accepted, c->is_resolving,
3085          c->is_connecting, c->is_tls, c->is_tls_hs, c->is_udp, c->is_websocket,
3086          c->is_hexdumping, c->is_draining, c->is_closing, c->is_readable,
3087          c->is_writable, (long) c->recv.len, n, (long) len, MG_SOCK_ERRNO));
3088     if (n == 0) {
3089       // Do nothing
3090     } else if (n < 0) {
3091       c->is_closing = 1;  // Error, or normal termination
3092     } else if (n > 0) {
3093       struct mg_str evd = mg_str_n(buf, (size_t) n);
3094       if (c->is_hexdumping) {
3095         char *s = mg_hexdump(buf, (size_t) n);
3096         LOG(LL_INFO, ("\n-- %lu %s %s %ld\n%s", c->id, c->label, "<-", n, s));
3097         free(s);
3098       }
3099       c->recv.len += (size_t) n;
3100       mg_call(c, MG_EV_READ, &evd);
3101     }
3102   }
3103   return n;
3104 }
3105
3106 static void write_conn(struct mg_connection *c) {
3107   char *buf = (char *) c->send.buf;
3108   size_t len = c->send.len;
3109   long n = c->is_tls ? mg_tls_send(c, buf, len) : mg_sock_send(c, buf, len);
3110
3111   LOG(n > 0 ? LL_VERBOSE_DEBUG : LL_DEBUG,
3112       ("%-3lu %d%d%d%d%d%d%d%d%d%d%d%d%d%d %7ld %ld err %d", c->id,
3113        c->is_listening, c->is_client, c->is_accepted, c->is_resolving,
3114        c->is_connecting, c->is_tls, c->is_tls_hs, c->is_udp, c->is_websocket,
3115        c->is_hexdumping, c->is_draining, c->is_closing, c->is_readable,
3116        c->is_writable, (long) c->send.len, n, MG_SOCK_ERRNO));
3117
3118   if (n == 0) {
3119     // Do nothing
3120   } else if (n < 0) {
3121     c->is_closing = 1;  // Error, or normal termination
3122   } else if (n > 0) {
3123     // Hexdump before deleting
3124     if (c->is_hexdumping) {
3125       char *s = mg_hexdump(buf, (size_t) n);
3126       LOG(LL_INFO, ("\n-- %lu %s %s %ld\n%s", c->id, c->label, "<-", n, s));
3127       free(s);
3128     }
3129     mg_iobuf_del(&c->send, 0, (size_t) n);
3130     if (c->send.len == 0) mg_iobuf_resize(&c->send, 0);
3131     mg_call(c, MG_EV_WRITE, &n);
3132     // if (c->send.len == 0) mg_iobuf_resize(&c->send, 0);
3133   }
3134 }
3135
3136 static void close_conn(struct mg_connection *c) {
3137   mg_resolve_cancel(c);  // Close any pending DNS query
3138   LIST_DELETE(struct mg_connection, &c->mgr->conns, c);
3139   if (c == c->mgr->dns4.c) c->mgr->dns4.c = NULL;
3140   if (c == c->mgr->dns6.c) c->mgr->dns6.c = NULL;
3141   // Order of operations is important. `MG_EV_CLOSE` event must be fired
3142   // before we deallocate received data, see #1331
3143   mg_call(c, MG_EV_CLOSE, NULL);
3144   LOG(LL_DEBUG, ("%lu closed", c->id));
3145   if (FD(c) != INVALID_SOCKET) {
3146     closesocket(FD(c));
3147 #if MG_ARCH == MG_ARCH_FREERTOS_TCP
3148     FreeRTOS_FD_CLR(c->fd, c->mgr->ss, eSELECT_ALL);
3149 #endif
3150     c->fd = S2PTR(INVALID_SOCKET);
3151   }
3152   mg_tls_free(c);
3153   mg_iobuf_free(&c->recv);
3154   mg_iobuf_free(&c->send);
3155   memset(c, 0, sizeof(*c));
3156   free(c);
3157 }
3158
3159 static void setsockopts(struct mg_connection *c) {
3160 #if MG_ARCH == MG_ARCH_FREERTOS_TCP || MG_ARCH == MG_ARCH_AZURERTOS
3161   (void) c;
3162 #else
3163   int on = 1;
3164 #if !defined(SOL_TCP)
3165 #define SOL_TCP IPPROTO_TCP
3166 #endif
3167   setsockopt(FD(c), SOL_TCP, TCP_NODELAY, (char *) &on, sizeof(on));
3168 #if defined(TCP_QUICKACK)
3169   setsockopt(FD(c), SOL_TCP, TCP_QUICKACK, (char *) &on, sizeof(on));
3170 #endif
3171   setsockopt(FD(c), SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on));
3172 #if (defined(ESP32) && ESP32) || (defined(ESP8266) && ESP8266) || \
3173     defined(__linux__)
3174   int idle = 60;
3175   setsockopt(FD(c), IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle));
3176 #endif
3177 #if !defined(_WIN32) && !defined(__QNX__)
3178   {
3179     int cnt = 3, intvl = 20;
3180     setsockopt(FD(c), IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt));
3181     setsockopt(FD(c), IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl));
3182   }
3183 #endif
3184 #endif
3185 }
3186
3187 void mg_connect_resolved(struct mg_connection *c) {
3188   char buf[40];
3189   int type = c->is_udp ? SOCK_DGRAM : SOCK_STREAM;
3190   int rc, af = c->peer.is_ip6 ? AF_INET6 : AF_INET;
3191   mg_straddr(c, buf, sizeof(buf));
3192   c->fd = S2PTR(socket(af, type, 0));
3193   if (FD(c) == INVALID_SOCKET) {
3194     mg_error(c, "socket(): %d", MG_SOCK_ERRNO);
3195   } else {
3196     union usa usa;
3197     socklen_t slen = tousa(&c->peer, &usa);
3198     if (c->is_udp == 0) mg_set_non_blocking_mode(FD(c));
3199     if (c->is_udp == 0) setsockopts(c);
3200     mg_call(c, MG_EV_RESOLVE, NULL);
3201     if ((rc = connect(FD(c), &usa.sa, slen)) == 0) {
3202       mg_call(c, MG_EV_CONNECT, NULL);
3203     } else if (mg_sock_would_block()) {
3204       c->is_connecting = 1;
3205     } else {
3206       mg_error(c, "connect: %d", MG_SOCK_ERRNO);
3207     }
3208   }
3209 }
3210
3211 struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
3212                                  mg_event_handler_t fn, void *fn_data) {
3213   struct mg_connection *c = NULL;
3214   if ((c = alloc_conn(mgr, 1, INVALID_SOCKET)) == NULL) {
3215     LOG(LL_ERROR, ("OOM"));
3216   } else {
3217     struct mg_str host = mg_url_host(url);
3218     LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
3219     c->is_udp = (strncmp(url, "udp:", 4) == 0);
3220     c->peer.port = mg_htons(mg_url_port(url));
3221     c->fn = fn;
3222     c->fn_data = fn_data;
3223     LOG(LL_DEBUG, ("%lu -> %s", c->id, url));
3224     mg_call(c, MG_EV_OPEN, NULL);
3225     mg_resolve(c, &host, mgr->dnstimeout);
3226   }
3227   return c;
3228 }
3229
3230 static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) {
3231   struct mg_connection *c = NULL;
3232   union usa usa;
3233   socklen_t sa_len = sizeof(usa);
3234   SOCKET fd = accept(FD(lsn), &usa.sa, &sa_len);
3235   if (fd == INVALID_SOCKET) {
3236 #if MG_ARCH == MG_ARCH_AZURERTOS
3237     // AzureRTOS, in non-block socket mode can mark listening socket readable
3238     // even it is not. See comment for 'select' func implementation in nx_bsd.c
3239     // That's not an error, just should try later
3240     if (MG_SOCK_ERRNO != EAGAIN)
3241 #endif
3242       LOG(LL_ERROR, ("%lu accept failed, errno %d", lsn->id, MG_SOCK_ERRNO));
3243 #if (!defined(_WIN32) && (MG_ARCH != MG_ARCH_FREERTOS_TCP))
3244   } else if ((long) fd >= FD_SETSIZE) {
3245     LOG(LL_ERROR, ("%ld > %ld", (long) fd, (long) FD_SETSIZE));
3246     closesocket(fd);
3247 #endif
3248   } else if ((c = alloc_conn(mgr, 0, fd)) == NULL) {
3249     LOG(LL_ERROR, ("%lu OOM", lsn->id));
3250     closesocket(fd);
3251   } else {
3252     char buf[40];
3253     tomgaddr(&usa, &c->peer, sa_len != sizeof(usa.sin));
3254     mg_straddr(c, buf, sizeof(buf));
3255     LOG(LL_DEBUG, ("%lu accepted %s", c->id, buf));
3256     mg_set_non_blocking_mode(FD(c));
3257     setsockopts(c);
3258     LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
3259     c->is_accepted = 1;
3260     c->is_hexdumping = lsn->is_hexdumping;
3261     c->pfn = lsn->pfn;
3262     c->pfn_data = lsn->pfn_data;
3263     c->fn = lsn->fn;
3264     c->fn_data = lsn->fn_data;
3265     mg_call(c, MG_EV_OPEN, NULL);
3266     mg_call(c, MG_EV_ACCEPT, NULL);
3267   }
3268 }
3269
3270 static bool mg_socketpair(SOCKET sp[2], union usa usa[2]) {
3271   socklen_t n = sizeof(usa[0].sin);
3272   bool result = false;
3273
3274   (void) memset(&usa[0], 0, sizeof(usa[0]));
3275   usa[0].sin.sin_family = AF_INET;
3276   *(uint32_t *) &usa->sin.sin_addr = mg_htonl(0x7f000001);  // 127.0.0.1
3277   usa[1] = usa[0];
3278
3279   if ((sp[0] = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET &&
3280       (sp[1] = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET &&
3281       bind(sp[0], &usa[0].sa, n) == 0 && bind(sp[1], &usa[1].sa, n) == 0 &&
3282       getsockname(sp[0], &usa[0].sa, &n) == 0 &&
3283       getsockname(sp[1], &usa[1].sa, &n) == 0 &&
3284       connect(sp[0], &usa[1].sa, n) == 0 &&
3285       connect(sp[1], &usa[0].sa, n) == 0) {
3286     mg_set_non_blocking_mode(sp[1]);  // Set close-on-exec
3287     result = true;
3288   } else {
3289     if (sp[0] != INVALID_SOCKET) closesocket(sp[0]);
3290     if (sp[1] != INVALID_SOCKET) closesocket(sp[1]);
3291     sp[0] = sp[1] = INVALID_SOCKET;
3292   }
3293
3294   return result;
3295 }
3296
3297 void mg_mgr_wakeup(struct mg_connection *c) {
3298   LOG(LL_INFO, ("skt: %p", c->pfn_data));
3299   send((SOCKET) (size_t) c->pfn_data, "\x01", 1, MSG_NONBLOCKING);
3300 }
3301
3302 static void pf1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
3303   if (ev == MG_EV_READ) mg_iobuf_free(&c->recv);
3304   (void) ev_data, (void) fn_data;
3305 }
3306
3307 struct mg_connection *mg_mkpipe(struct mg_mgr *mgr, mg_event_handler_t fn,
3308                                 void *fn_data) {
3309   union usa usa[2];
3310   SOCKET sp[2] = {INVALID_SOCKET, INVALID_SOCKET};
3311   struct mg_connection *c = NULL;
3312   if (!mg_socketpair(sp, usa)) {
3313     LOG(LL_ERROR, ("Cannot create socket pair"));
3314   } else if ((c = alloc_conn(mgr, false, sp[1])) == NULL) {
3315     closesocket(sp[0]);
3316     closesocket(sp[1]);
3317     LOG(LL_ERROR, ("OOM"));
3318   } else {
3319     LOG(LL_INFO, ("pipe %lu", (unsigned long) sp[0]));
3320     tomgaddr(&usa[0], &c->peer, false);
3321     c->is_udp = 1;
3322     c->pfn = pf1;
3323     c->pfn_data = (void *) (size_t) sp[0];
3324     c->fn = fn;
3325     c->fn_data = fn_data;
3326     mg_call(c, MG_EV_OPEN, NULL);
3327     LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
3328   }
3329   return c;
3330 }
3331
3332 struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
3333                                 mg_event_handler_t fn, void *fn_data) {
3334   struct mg_connection *c = NULL;
3335   bool is_udp = strncmp(url, "udp:", 4) == 0;
3336   struct mg_addr addr;
3337   SOCKET fd = mg_open_listener(url, &addr);
3338   if (fd == INVALID_SOCKET) {
3339     LOG(LL_ERROR, ("Failed: %s, errno %d", url, MG_SOCK_ERRNO));
3340   } else if ((c = alloc_conn(mgr, 0, fd)) == NULL) {
3341     LOG(LL_ERROR, ("OOM %s", url));
3342     closesocket(fd);
3343   } else {
3344     memcpy(&c->peer, &addr, sizeof(struct mg_addr));
3345     c->fd = S2PTR(fd);
3346     c->is_listening = 1;
3347     c->is_udp = is_udp;
3348     LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
3349     c->fn = fn;
3350     c->fn_data = fn_data;
3351     mg_call(c, MG_EV_OPEN, NULL);
3352     LOG(LL_DEBUG,
3353         ("%lu accepting on %s (port %u)", c->id, url, mg_ntohs(c->peer.port)));
3354   }
3355   return c;
3356 }
3357
3358 static void mg_iotest(struct mg_mgr *mgr, int ms) {
3359 #if MG_ARCH == MG_ARCH_FREERTOS_TCP
3360   struct mg_connection *c;
3361   for (c = mgr->conns; c != NULL; c = c->next) {
3362     if (c->is_closing || c->is_resolving || FD(c) == INVALID_SOCKET) continue;
3363     FreeRTOS_FD_SET(c->fd, mgr->ss, eSELECT_READ | eSELECT_EXCEPT);
3364     if (c->is_connecting || (c->send.len > 0 && c->is_tls_hs == 0))
3365       FreeRTOS_FD_SET(c->fd, mgr->ss, eSELECT_WRITE);
3366   }
3367   FreeRTOS_select(mgr->ss, pdMS_TO_TICKS(ms));
3368   for (c = mgr->conns; c != NULL; c = c->next) {
3369     EventBits_t bits = FreeRTOS_FD_ISSET(c->fd, mgr->ss);
3370     c->is_readable = bits & (eSELECT_READ | eSELECT_EXCEPT) ? 1 : 0;
3371     c->is_writable = bits & eSELECT_WRITE ? 1 : 0;
3372     FreeRTOS_FD_CLR(c->fd, mgr->ss,
3373                     eSELECT_READ | eSELECT_EXCEPT | eSELECT_WRITE);
3374   }
3375 #else
3376   struct timeval tv = {ms / 1000, (ms % 1000) * 1000};
3377   struct mg_connection *c;
3378   fd_set rset, wset;
3379   SOCKET maxfd = 0;
3380   int rc;
3381
3382   FD_ZERO(&rset);
3383   FD_ZERO(&wset);
3384
3385   for (c = mgr->conns; c != NULL; c = c->next) {
3386     if (c->is_closing || c->is_resolving || FD(c) == INVALID_SOCKET) continue;
3387     FD_SET(FD(c), &rset);
3388     if (FD(c) > maxfd) maxfd = FD(c);
3389     if (c->is_connecting || (c->send.len > 0 && c->is_tls_hs == 0))
3390       FD_SET(FD(c), &wset);
3391   }
3392
3393   if ((rc = select((int) maxfd + 1, &rset, &wset, NULL, &tv)) < 0) {
3394     LOG(LL_DEBUG, ("select: %d %d", rc, MG_SOCK_ERRNO));
3395     FD_ZERO(&rset);
3396     FD_ZERO(&wset);
3397   }
3398
3399   for (c = mgr->conns; c != NULL; c = c->next) {
3400     // TLS might have stuff buffered, so dig everything
3401     c->is_readable = FD(c) != INVALID_SOCKET && FD_ISSET(FD(c), &rset);
3402     c->is_writable = FD(c) != INVALID_SOCKET && FD_ISSET(FD(c), &wset);
3403   }
3404 #endif
3405 }
3406
3407 static void connect_conn(struct mg_connection *c) {
3408   int rc = 0;
3409 #if MG_ARCH != MG_ARCH_FREERTOS_TCP
3410   socklen_t len = sizeof(rc);
3411   if (getsockopt(FD(c), SOL_SOCKET, SO_ERROR, (char *) &rc, &len)) rc = 1;
3412 #endif
3413   if (rc == EAGAIN || rc == EWOULDBLOCK) rc = 0;
3414   c->is_connecting = 0;
3415   if (rc) {
3416     char buf[40];
3417     mg_error(c, "error connecting to %s", mg_straddr(c, buf, sizeof(buf)));
3418   } else {
3419     if (c->is_tls_hs) mg_tls_handshake(c);
3420     mg_call(c, MG_EV_CONNECT, NULL);
3421   }
3422 }
3423
3424 void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
3425   struct mg_connection *c, *tmp;
3426   unsigned long now;
3427
3428   mg_iotest(mgr, ms);
3429   now = mg_millis();
3430   mg_timer_poll(now);
3431
3432   for (c = mgr->conns; c != NULL; c = tmp) {
3433     tmp = c->next;
3434     mg_call(c, MG_EV_POLL, &now);
3435     LOG(LL_VERBOSE_DEBUG,
3436         ("%lu %c%c %c%c%c%c%c", c->id, c->is_readable ? 'r' : '-',
3437          c->is_writable ? 'w' : '-', c->is_tls ? 'T' : 't',
3438          c->is_connecting ? 'C' : 'c', c->is_tls_hs ? 'H' : 'h',
3439          c->is_resolving ? 'R' : 'r', c->is_closing ? 'C' : 'c'));
3440     if (c->is_resolving || c->is_closing) {
3441       // Do nothing
3442     } else if (c->is_listening && c->is_udp == 0) {
3443       if (c->is_readable) accept_conn(mgr, c);
3444     } else if (c->is_connecting) {
3445       if (c->is_readable || c->is_writable) connect_conn(c);
3446     } else if (c->is_tls_hs) {
3447       if ((c->is_readable || c->is_writable)) mg_tls_handshake(c);
3448     } else {
3449       if (c->is_readable) read_conn(c);
3450       if (c->is_writable) write_conn(c);
3451       while (c->is_tls && read_conn(c) > 0) (void) 0;  // Read buffered TLS data
3452     }
3453
3454     if (c->is_draining && c->send.len == 0) c->is_closing = 1;
3455     if (c->is_closing) close_conn(c);
3456   }
3457 }
3458 #endif
3459
3460 #ifdef MG_ENABLE_LINES
3461 #line 1 "src/ssi.c"
3462 #endif
3463
3464
3465
3466
3467 #ifndef MG_MAX_SSI_DEPTH
3468 #define MG_MAX_SSI_DEPTH 5
3469 #endif
3470
3471 #if MG_ENABLE_SSI
3472 static char *mg_ssi(const char *path, const char *root, int depth) {
3473   struct mg_iobuf b = {NULL, 0, 0};
3474   FILE *fp = fopen(path, "rb");
3475   if (fp != NULL) {
3476     char buf[BUFSIZ], arg[sizeof(buf)];
3477     int ch, intag = 0;
3478     size_t len = 0, align = MG_IO_SIZE;
3479     while ((ch = fgetc(fp)) != EOF) {
3480       if (intag && ch == '>' && buf[len - 1] == '-' && buf[len - 2] == '-') {
3481         buf[len++] = (char) (ch & 0xff);
3482         if (sscanf(buf, "<!--#include file=\"%[^\"]", arg)) {
3483           char tmp[MG_PATH_MAX + BUFSIZ + 10],
3484               *p = (char *) path + strlen(path), *data;
3485           while (p > path && p[-1] != MG_DIRSEP && p[-1] != '/') p--;
3486           snprintf(tmp, sizeof(tmp), "%.*s%s", (int) (p - path), path, arg);
3487           if (depth < MG_MAX_SSI_DEPTH &&
3488               (data = mg_ssi(tmp, root, depth + 1)) != NULL) {
3489             mg_iobuf_add(&b, b.len, data, strlen(data), align);
3490             free(data);
3491           } else {
3492             LOG(LL_ERROR, ("%s: file=%s error or too deep", path, arg));
3493           }
3494         } else if (sscanf(buf, "<!--#include virtual=\"%[^\"]", arg)) {
3495           char tmp[MG_PATH_MAX + BUFSIZ + 10], *data;
3496           snprintf(tmp, sizeof(tmp), "%s%s", root, arg);
3497           if (depth < MG_MAX_SSI_DEPTH &&
3498               (data = mg_ssi(tmp, root, depth + 1)) != NULL) {
3499             mg_iobuf_add(&b, b.len, data, strlen(data), align);
3500             free(data);
3501           } else {
3502             LOG(LL_ERROR, ("%s: virtual=%s error or too deep", path, arg));
3503           }
3504         } else {
3505           // Unknown SSI tag
3506           LOG(LL_INFO, ("Unknown SSI tag: %.*s", (int) len, buf));
3507           mg_iobuf_add(&b, b.len, buf, len, align);
3508         }
3509         intag = 0;
3510         len = 0;
3511       } else if (ch == '<') {
3512         intag = 1;
3513         if (len > 0) mg_iobuf_add(&b, b.len, buf, len, align);
3514         len = 0;
3515         buf[len++] = (char) (ch & 0xff);
3516       } else if (intag) {
3517         if (len == 5 && strncmp(buf, "<!--#", 5) != 0) {
3518           intag = 0;
3519         } else if (len >= sizeof(buf) - 2) {
3520           LOG(LL_ERROR, ("%s: SSI tag is too large", path));
3521           len = 0;
3522         }
3523         buf[len++] = (char) (ch & 0xff);
3524       } else {
3525         buf[len++] = (char) (ch & 0xff);
3526         if (len >= sizeof(buf)) {
3527           mg_iobuf_add(&b, b.len, buf, len, align);
3528           len = 0;
3529         }
3530       }
3531     }
3532     if (len > 0) mg_iobuf_add(&b, b.len, buf, len, align);
3533     if (b.len > 0) mg_iobuf_add(&b, b.len, "", 1, align);  // nul-terminate
3534     fclose(fp);
3535   }
3536   (void) depth;
3537   (void) root;
3538   return (char *) b.buf;
3539 }
3540
3541 void mg_http_serve_ssi(struct mg_connection *c, const char *root,
3542                        const char *fullpath) {
3543   const char *headers = "Content-Type: text/html; charset=utf-8\r\n";
3544   char *data = mg_ssi(fullpath, root, 0);
3545   mg_http_reply(c, 200, headers, "%s", data == NULL ? "" : data);
3546   free(data);
3547 }
3548 #else
3549 void mg_http_serve_ssi(struct mg_connection *c, const char *root,
3550                        const char *fullpath) {
3551   mg_http_reply(c, 501, NULL, "SSI not enabled");
3552   (void) root, (void) fullpath;
3553 }
3554 #endif
3555
3556 #ifdef MG_ENABLE_LINES
3557 #line 1 "src/str.c"
3558 #endif
3559
3560 #include <stdlib.h>
3561
3562 struct mg_str mg_str_s(const char *s) {
3563   struct mg_str str = {s, s == NULL ? 0 : strlen(s)};
3564   return str;
3565 }
3566
3567 struct mg_str mg_str_n(const char *s, size_t n) {
3568   struct mg_str str = {s, n};
3569   return str;
3570 }
3571
3572 int mg_lower(const char *s) {
3573   return tolower(*(const unsigned char *) s);
3574 }
3575
3576 int mg_ncasecmp(const char *s1, const char *s2, size_t len) {
3577   int diff = 0;
3578   if (len > 0) do {
3579       diff = mg_lower(s1++) - mg_lower(s2++);
3580     } while (diff == 0 && s1[-1] != '\0' && --len > 0);
3581   return diff;
3582 }
3583
3584 int mg_casecmp(const char *s1, const char *s2) {
3585   return mg_ncasecmp(s1, s2, (size_t) ~0);
3586 }
3587
3588 int mg_vcmp(const struct mg_str *s1, const char *s2) {
3589   size_t n2 = strlen(s2), n1 = s1->len;
3590   int r = strncmp(s1->ptr, s2, (n1 < n2) ? n1 : n2);
3591   if (r == 0) return (int) (n1 - n2);
3592   return r;
3593 }
3594
3595 int mg_vcasecmp(const struct mg_str *str1, const char *str2) {
3596   size_t n2 = strlen(str2), n1 = str1->len;
3597   int r = mg_ncasecmp(str1->ptr, str2, (n1 < n2) ? n1 : n2);
3598   if (r == 0) return (int) (n1 - n2);
3599   return r;
3600 }
3601
3602 struct mg_str mg_strdup(const struct mg_str s) {
3603   struct mg_str r = {NULL, 0};
3604   if (s.len > 0 && s.ptr != NULL) {
3605     char *sc = (char *) calloc(1, s.len + 1);
3606     if (sc != NULL) {
3607       memcpy(sc, s.ptr, s.len);
3608       sc[s.len] = '\0';
3609       r.ptr = sc;
3610       r.len = s.len;
3611     }
3612   }
3613   return r;
3614 }
3615
3616 int mg_strcmp(const struct mg_str str1, const struct mg_str str2) {
3617   size_t i = 0;
3618   while (i < str1.len && i < str2.len) {
3619     int c1 = str1.ptr[i];
3620     int c2 = str2.ptr[i];
3621     if (c1 < c2) return -1;
3622     if (c1 > c2) return 1;
3623     i++;
3624   }
3625   if (i < str1.len) return 1;
3626   if (i < str2.len) return -1;
3627   return 0;
3628 }
3629
3630 const char *mg_strstr(const struct mg_str haystack,
3631                       const struct mg_str needle) {
3632   size_t i;
3633   if (needle.len > haystack.len) return NULL;
3634   for (i = 0; i <= haystack.len - needle.len; i++) {
3635     if (memcmp(haystack.ptr + i, needle.ptr, needle.len) == 0) {
3636       return haystack.ptr + i;
3637     }
3638   }
3639   return NULL;
3640 }
3641
3642 struct mg_str mg_strstrip(struct mg_str s) {
3643   while (s.len > 0 && isspace((int) *s.ptr)) s.ptr++, s.len--;
3644   while (s.len > 0 && isspace((int) *(s.ptr + s.len - 1))) s.len--;
3645   return s;
3646 }
3647
3648 #ifdef MG_ENABLE_LINES
3649 #line 1 "src/timer.c"
3650 #endif
3651 // Copyright (c) Cesanta Software Limited
3652 // All rights reserved
3653
3654
3655
3656
3657 struct mg_timer *g_timers;
3658
3659 void mg_timer_init(struct mg_timer *t, unsigned long ms, unsigned flags,
3660                    void (*fn)(void *), void *arg) {
3661   struct mg_timer tmp = {ms, 0UL, flags, fn, arg, g_timers};
3662   *t = tmp;
3663   g_timers = t;
3664   if (flags & MG_TIMER_RUN_NOW) fn(arg);
3665 }
3666
3667 void mg_timer_free(struct mg_timer *t) {
3668   struct mg_timer **head = &g_timers;
3669   while (*head && *head != t) head = &(*head)->next;
3670   if (*head) *head = t->next;
3671 }
3672
3673 void mg_timer_poll(unsigned long now_ms) {
3674   // If time goes back (wrapped around), reset timers
3675   struct mg_timer *t, *tmp;
3676   static unsigned long oldnow;  // Timestamp in a previous invocation
3677   if (oldnow > now_ms) {        // If it is wrapped, reset timers
3678     for (t = g_timers; t != NULL; t = t->next) t->expire = 0;
3679   }
3680   oldnow = now_ms;
3681
3682   for (t = g_timers; t != NULL; t = tmp) {
3683     tmp = t->next;
3684     if (t->expire == 0) t->expire = now_ms + t->period_ms;
3685     if (t->expire > now_ms) continue;
3686     t->fn(t->arg);
3687     // Try to tick timers with the given period as accurate as possible,
3688     // even if this polling function is called with some random period.
3689     t->expire = now_ms - t->expire > (unsigned long) t->period_ms
3690                     ? now_ms + t->period_ms
3691                     : t->expire + t->period_ms;
3692     if (!(t->flags & MG_TIMER_REPEAT)) mg_timer_free(t);
3693   }
3694 }
3695
3696 #ifdef MG_ENABLE_LINES
3697 #line 1 "src/tls_dummy.c"
3698 #endif
3699
3700
3701 #if !MG_ENABLE_MBEDTLS && !MG_ENABLE_OPENSSL && !MG_ENABLE_CUSTOM_TLS
3702 void mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
3703   (void) opts;
3704   mg_error(c, "TLS is not enabled");
3705 }
3706 void mg_tls_handshake(struct mg_connection *c) {
3707   (void) c;
3708 }
3709 void mg_tls_free(struct mg_connection *c) {
3710   (void) c;
3711 }
3712 long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
3713   return c == NULL || buf == NULL || len == 0 ? 0 : -1;
3714 }
3715 long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
3716   return c == NULL || buf == NULL || len == 0 ? 0 : -1;
3717 }
3718 #endif
3719
3720 #ifdef MG_ENABLE_LINES
3721 #line 1 "src/tls_mbed.c"
3722 #endif
3723
3724
3725 #if MG_ENABLE_MBEDTLS
3726 void mg_tls_handshake(struct mg_connection *c) {
3727   struct mg_tls *tls = (struct mg_tls *) c->tls;
3728   int rc;
3729   mbedtls_ssl_set_bio(&tls->ssl, &c->fd, mbedtls_net_send, mbedtls_net_recv, 0);
3730   rc = mbedtls_ssl_handshake(&tls->ssl);
3731   if (rc == 0) {  // Success
3732     LOG(LL_DEBUG, ("%lu success", c->id));
3733     c->is_tls_hs = 0;
3734   } else if (rc == MBEDTLS_ERR_SSL_WANT_READ ||
3735              rc == MBEDTLS_ERR_SSL_WANT_WRITE) {  // Still pending
3736     LOG(LL_VERBOSE_DEBUG, ("%lu pending, %d%d %d (-%#x)", c->id,
3737                            c->is_connecting, c->is_tls_hs, rc, -rc));
3738   } else {
3739     mg_error(c, "TLS handshake: -%#x", -rc);  // Error
3740   }
3741 }
3742
3743 static int mbed_rng(void *ctx, unsigned char *buf, size_t len) {
3744   mg_random(buf, len);
3745   (void) ctx;
3746   return 0;
3747 }
3748
3749 static void debug_cb(void *c, int lev, const char *s, int n, const char *s2) {
3750   n = (int) strlen(s2) - 1;
3751   LOG(LL_VERBOSE_DEBUG, ("%p %.*s", ((struct mg_connection *) c)->fd, n, s2));
3752   (void) s;
3753   (void) c;
3754   (void) lev;
3755 }
3756
3757 #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
3758 static int rng_get(void *p_rng, unsigned char *buf, size_t len) {
3759   (void) p_rng;
3760   mg_random(buf, len);
3761   return 0;
3762 }
3763 #endif
3764
3765 void mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
3766   struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
3767   int rc = 0;
3768   const char *ca = opts->ca == NULL     ? "-"
3769                    : opts->ca[0] == '-' ? "(emb)"
3770                                         : opts->ca;
3771   const char *crl = opts->crl == NULL     ? "-"
3772                     : opts->crl[0] == '-' ? "(emb)"
3773                                           : opts->crl;
3774   const char *cert = opts->cert == NULL     ? "-"
3775                      : opts->cert[0] == '-' ? "(emb)"
3776                                             : opts->cert;
3777   const char *certkey = opts->certkey == NULL     ? "-"
3778                         : opts->certkey[0] == '-' ? "(emb)"
3779                                                   : opts->certkey;
3780   if (tls == NULL) {
3781     mg_error(c, "TLS OOM");
3782     goto fail;
3783   }
3784   LOG(LL_DEBUG, ("%lu Setting TLS, CA: %s, CRL: %s, cert: %s, key: %s", c->id,
3785                  ca, crl, cert, certkey));
3786   mbedtls_ssl_init(&tls->ssl);
3787   mbedtls_ssl_config_init(&tls->conf);
3788   mbedtls_x509_crt_init(&tls->ca);
3789   mbedtls_x509_crl_init(&tls->crl);
3790   mbedtls_x509_crt_init(&tls->cert);
3791   mbedtls_pk_init(&tls->pk);
3792   mbedtls_ssl_conf_dbg(&tls->conf, debug_cb, c);
3793   //#if !defined(ESP_PLATFORM)
3794   // mbedtls_debug_set_threshold(5);
3795   //#endif
3796   if ((rc = mbedtls_ssl_config_defaults(
3797            &tls->conf,
3798            c->is_client ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
3799            MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
3800     mg_error(c, "tls defaults %#x", -rc);
3801     goto fail;
3802   }
3803   mbedtls_ssl_conf_rng(&tls->conf, mbed_rng, c);
3804   if (opts->ca == NULL || strcmp(opts->ca, "*") == 0) {
3805     mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE);
3806   }
3807   if (opts->ca != NULL && opts->ca[0] != '\0') {
3808     if (opts->crl != NULL && opts->crl[0] != '\0') {
3809       rc = opts->crl[0] == '-'
3810                ? mbedtls_x509_crl_parse(&tls->crl, (uint8_t *) opts->crl,
3811                                         strlen(opts->crl) + 1)
3812                : mbedtls_x509_crl_parse_file(&tls->crl, opts->crl);
3813       if (rc != 0) {
3814         mg_error(c, "parse(%s) err %#x", crl, -rc);
3815         goto fail;
3816       }
3817     }
3818 #if defined(MBEDTLS_X509_CA_CHAIN_ON_DISK)
3819     tls->cafile = strdup(opts->ca);
3820     rc = mbedtls_ssl_conf_ca_chain_file(&tls->conf, tls->cafile, &tls->crl);
3821     if (rc != 0) {
3822       mg_error(c, "parse on-disk chain(%s) err %#x", ca, -rc);
3823       goto fail;
3824     }
3825 #else
3826     rc = opts->ca[0] == '-'
3827              ? mbedtls_x509_crt_parse(&tls->ca, (uint8_t *) opts->ca,
3828                                       strlen(opts->ca) + 1)
3829              : mbedtls_x509_crt_parse_file(&tls->ca, opts->ca);
3830     if (rc != 0) {
3831       mg_error(c, "parse(%s) err %#x", ca, -rc);
3832       goto fail;
3833     }
3834     mbedtls_ssl_conf_ca_chain(&tls->conf, &tls->ca, &tls->crl);
3835 #endif
3836     if (opts->srvname.len > 0) {
3837       char mem[128], *buf = mem;
3838       mg_asprintf(&buf, sizeof(mem), "%.*s", (int) opts->srvname.len,
3839                   opts->srvname.ptr);
3840       mbedtls_ssl_set_hostname(&tls->ssl, buf);
3841       if (buf != mem) free(buf);
3842     }
3843     mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
3844   }
3845   if (opts->cert != NULL && opts->cert[0] != '\0') {
3846     const char *key = opts->certkey;
3847     if (key == NULL) {
3848       key = opts->cert;
3849       certkey = cert;
3850     }
3851     rc = opts->cert[0] == '-'
3852              ? mbedtls_x509_crt_parse(&tls->cert, (uint8_t *) opts->cert,
3853                                       strlen(opts->cert) + 1)
3854              : mbedtls_x509_crt_parse_file(&tls->cert, opts->cert);
3855     if (rc != 0) {
3856       mg_error(c, "parse(%s) err %#x", cert, -rc);
3857       goto fail;
3858     }
3859     rc = key[0] == '-' ? mbedtls_pk_parse_key(&tls->pk, (uint8_t *) key,
3860                                               strlen(key) + 1, NULL, 0 RNG)
3861                        : mbedtls_pk_parse_keyfile(&tls->pk, key, NULL RNG);
3862     if (rc != 0) {
3863       mg_error(c, "tls key(%s) %#x", certkey, -rc);
3864       goto fail;
3865     }
3866     rc = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->cert, &tls->pk);
3867     if (rc != 0) {
3868       mg_error(c, "own cert %#x", -rc);
3869       goto fail;
3870     }
3871   }
3872   if ((rc = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) {
3873     mg_error(c, "setup err %#x", -rc);
3874     goto fail;
3875   }
3876   c->tls = tls;
3877   c->is_tls = 1;
3878   c->is_tls_hs = 1;
3879   if (c->is_client && c->is_resolving == 0 && c->is_connecting == 0) {
3880     mg_tls_handshake(c);
3881   }
3882   return;
3883 fail:
3884   c->is_closing = 1;
3885   free(tls);
3886 }
3887
3888 long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
3889   struct mg_tls *tls = (struct mg_tls *) c->tls;
3890   long n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len);
3891   return n == 0 ? -1 : n == MBEDTLS_ERR_SSL_WANT_READ ? 0 : n;
3892 }
3893
3894 long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
3895   struct mg_tls *tls = (struct mg_tls *) c->tls;
3896   long n = mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf, len);
3897   return n == 0 ? -1 : n == MBEDTLS_ERR_SSL_WANT_WRITE ? 0 : n;
3898 }
3899
3900 void mg_tls_free(struct mg_connection *c) {
3901   struct mg_tls *tls = (struct mg_tls *) c->tls;
3902   if (tls == NULL) return;
3903   free(tls->cafile);
3904   mbedtls_ssl_free(&tls->ssl);
3905   mbedtls_pk_free(&tls->pk);
3906   mbedtls_x509_crt_free(&tls->ca);
3907   mbedtls_x509_crl_free(&tls->crl);
3908   mbedtls_x509_crt_free(&tls->cert);
3909   mbedtls_ssl_config_free(&tls->conf);
3910   free(tls);
3911   c->tls = NULL;
3912 }
3913 #endif
3914
3915 #ifdef MG_ENABLE_LINES
3916 #line 1 "src/tls_openssl.c"
3917 #endif
3918
3919
3920 #if MG_ENABLE_OPENSSL
3921 static int mg_tls_err(struct mg_tls *tls, int res) {
3922   int err = SSL_get_error(tls->ssl, res);
3923   // We've just fetched the last error from the queue.
3924   // Now we need to clear the error queue. If we do not, then the following
3925   // can happen (actually reported):
3926   //  - A new connection is accept()-ed with cert error (e.g. self-signed cert)
3927   //  - Since all accept()-ed connections share listener's context,
3928   //  - *ALL* SSL accepted connection report read error on the next poll cycle.
3929   //    Thus a single errored connection can close all the rest, unrelated ones.
3930   // Clearing the error keeps the shared SSL_CTX in an OK state.
3931
3932   if (err != 0) ERR_print_errors_fp(stderr);
3933   ERR_clear_error();
3934   if (err == SSL_ERROR_WANT_READ) return 0;
3935   if (err == SSL_ERROR_WANT_WRITE) return 0;
3936   return err;
3937 }
3938
3939 void mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
3940   struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
3941   const char *id = "mongoose";
3942   static unsigned char s_initialised = 0;
3943   int rc;
3944
3945   if (tls == NULL) {
3946     mg_error(c, "TLS OOM");
3947     goto fail;
3948   }
3949
3950   if (!s_initialised) {
3951     SSL_library_init();
3952     s_initialised++;
3953   }
3954   LOG(LL_DEBUG, ("%lu Setting TLS, CA: %s, cert: %s, key: %s", c->id,
3955                  opts->ca == NULL ? "null" : opts->ca,
3956                  opts->cert == NULL ? "null" : opts->cert,
3957                  opts->certkey == NULL ? "null" : opts->certkey));
3958   tls->ctx = c->is_client ? SSL_CTX_new(SSLv23_client_method())
3959                           : SSL_CTX_new(SSLv23_server_method());
3960   if ((tls->ssl = SSL_new(tls->ctx)) == NULL) {
3961     mg_error(c, "SSL_new");
3962     goto fail;
3963   }
3964   SSL_set_session_id_context(tls->ssl, (const uint8_t *) id,
3965                              (unsigned) strlen(id));
3966   // Disable deprecated protocols
3967   SSL_set_options(tls->ssl, SSL_OP_NO_SSLv2);
3968   SSL_set_options(tls->ssl, SSL_OP_NO_SSLv3);
3969   SSL_set_options(tls->ssl, SSL_OP_NO_TLSv1);
3970   SSL_set_options(tls->ssl, SSL_OP_NO_TLSv1_1);
3971 #ifdef MG_ENABLE_OPENSSL_NO_COMPRESSION
3972   SSL_set_options(tls->ssl, SSL_OP_NO_COMPRESSION);
3973 #endif
3974 #ifdef MG_ENABLE_OPENSSL_CIPHER_SERVER_PREFERENCE
3975   SSL_set_options(tls->ssl, SSL_OP_CIPHER_SERVER_PREFERENCE);
3976 #endif
3977
3978   if (opts->ca != NULL && opts->ca[0] != '\0') {
3979     SSL_set_verify(tls->ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3980                    NULL);
3981     if ((rc = SSL_CTX_load_verify_locations(tls->ctx, opts->ca, NULL)) != 1) {
3982       mg_error(c, "parse(%s): err %d", opts->ca, mg_tls_err(tls, rc));
3983       goto fail;
3984     }
3985   }
3986   if (opts->cert != NULL && opts->cert[0] != '\0') {
3987     const char *key = opts->certkey;
3988     if (key == NULL) key = opts->cert;
3989     if ((rc = SSL_use_certificate_file(tls->ssl, opts->cert, 1)) != 1) {
3990       mg_error(c, "Invalid SSL cert, err %d", mg_tls_err(tls, rc));
3991       goto fail;
3992     } else if ((rc = SSL_use_PrivateKey_file(tls->ssl, key, 1)) != 1) {
3993       mg_error(c, "Invalid SSL key, err %d", mg_tls_err(tls, rc));
3994       goto fail;
3995 #if OPENSSL_VERSION_NUMBER > 0x10100000L
3996     } else if ((rc = SSL_use_certificate_chain_file(tls->ssl, opts->cert)) !=
3997                1) {
3998       mg_error(c, "Invalid CA, err %d", mg_tls_err(tls, rc));
3999       goto fail;
4000 #endif
4001     } else {
4002       SSL_set_mode(tls->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
4003 #if OPENSSL_VERSION_NUMBER > 0x10002000L
4004       SSL_set_ecdh_auto(tls->ssl, 1);
4005 #endif
4006     }
4007   }
4008   if (opts->ciphers != NULL) SSL_set_cipher_list(tls->ssl, opts->ciphers);
4009   if (opts->srvname.len > 0) {
4010     char mem[128], *buf = mem;
4011     mg_asprintf(&buf, sizeof(mem), "%.*s", (int) opts->srvname.len,
4012                 opts->srvname.ptr);
4013     SSL_set_tlsext_host_name(tls->ssl, buf);
4014     if (buf != mem) free(buf);
4015   }
4016   c->tls = tls;
4017   c->is_tls = 1;
4018   c->is_tls_hs = 1;
4019   if (c->is_client && c->is_resolving == 0 && c->is_connecting == 0) {
4020     mg_tls_handshake(c);
4021   }
4022   c->is_hexdumping = 1;
4023   LOG(LL_DEBUG, ("%lu SSL %s OK", c->id, c->is_accepted ? "accept" : "client"));
4024   return;
4025 fail:
4026   c->is_closing = 1;
4027   free(tls);
4028 }
4029
4030 void mg_tls_handshake(struct mg_connection *c) {
4031   struct mg_tls *tls = (struct mg_tls *) c->tls;
4032   int rc;
4033   SSL_set_fd(tls->ssl, (int) (size_t) c->fd);
4034   rc = c->is_client ? SSL_connect(tls->ssl) : SSL_accept(tls->ssl);
4035   if (rc == 1) {
4036     LOG(LL_DEBUG, ("%lu success", c->id));
4037     c->is_tls_hs = 0;
4038   } else {
4039     int code = mg_tls_err(tls, rc);
4040     if (code != 0) mg_error(c, "tls hs: rc %d, err %d", rc, code);
4041   }
4042 }
4043
4044 void mg_tls_free(struct mg_connection *c) {
4045   struct mg_tls *tls = (struct mg_tls *) c->tls;
4046   if (tls == NULL) return;
4047   SSL_free(tls->ssl);
4048   SSL_CTX_free(tls->ctx);
4049   free(tls);
4050   c->tls = NULL;
4051 }
4052
4053 long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
4054   struct mg_tls *tls = (struct mg_tls *) c->tls;
4055   int n = SSL_read(tls->ssl, buf, (int) len);
4056   return n == 0 ? -1 : n < 0 && mg_tls_err(tls, n) == 0 ? 0 : n;
4057 }
4058
4059 long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
4060   struct mg_tls *tls = (struct mg_tls *) c->tls;
4061   int n = SSL_write(tls->ssl, buf, (int) len);
4062   return n == 0 ? -1 : n < 0 && mg_tls_err(tls, n) == 0 ? 0 : n;
4063 }
4064 #endif
4065
4066 #ifdef MG_ENABLE_LINES
4067 #line 1 "src/url.c"
4068 #endif
4069
4070 #include <stdlib.h>
4071
4072 struct url {
4073   size_t key, user, pass, host, port, uri, end;
4074 };
4075
4076 int mg_url_is_ssl(const char *url) {
4077   return strncmp(url, "wss:", 4) == 0 || strncmp(url, "https:", 6) == 0 ||
4078          strncmp(url, "mqtts:", 6) == 0 || strncmp(url, "ssl:", 4) == 0 ||
4079          strncmp(url, "tls:", 4) == 0;
4080 }
4081
4082 static struct url urlparse(const char *url) {
4083   size_t i;
4084   struct url u;
4085   memset(&u, 0, sizeof(u));
4086   for (i = 0; url[i] != '\0'; i++) {
4087     if (i > 0 && u.host == 0 && url[i - 1] == '/' && url[i] == '/') {
4088       u.host = i + 1;
4089       u.port = 0;
4090     } else if (url[i] == ']') {
4091       u.port = 0;  // IPv6 URLs, like http://[::1]/bar
4092     } else if (url[i] == ':' && u.port == 0 && u.uri == 0) {
4093       u.port = i + 1;
4094     } else if (url[i] == '@' && u.user == 0 && u.pass == 0) {
4095       u.user = u.host;
4096       u.pass = u.port;
4097       u.host = i + 1;
4098       u.port = 0;
4099     } else if (u.host && u.uri == 0 && url[i] == '/') {
4100       u.uri = i;
4101     }
4102   }
4103   u.end = i;
4104 #if 0
4105   printf("[%s] %d %d %d %d %d\n", url, u.user, u.pass, u.host, u.port, u.uri);
4106 #endif
4107   return u;
4108 }
4109
4110 struct mg_str mg_url_host(const char *url) {
4111   struct url u = urlparse(url);
4112   size_t n = u.port  ? u.port - u.host - 1
4113              : u.uri ? u.uri - u.host
4114                      : u.end - u.host;
4115   struct mg_str s = mg_str_n(url + u.host, n);
4116   return s;
4117 }
4118
4119 const char *mg_url_uri(const char *url) {
4120   struct url u = urlparse(url);
4121   return u.uri ? url + u.uri : "/";
4122 }
4123
4124 unsigned short mg_url_port(const char *url) {
4125   struct url u = urlparse(url);
4126   unsigned short port = 0;
4127   if (memcmp(url, "http:", 5) == 0 || memcmp(url, "ws:", 3) == 0) port = 80;
4128   if (memcmp(url, "wss:", 4) == 0 || memcmp(url, "https:", 6) == 0) port = 443;
4129   if (memcmp(url, "mqtt:", 5) == 0) port = 1883;
4130   if (memcmp(url, "mqtts:", 6) == 0) port = 8883;
4131   if (u.port) port = (unsigned short) atoi(url + u.port);
4132   return port;
4133 }
4134
4135 struct mg_str mg_url_user(const char *url) {
4136   struct url u = urlparse(url);
4137   struct mg_str s = mg_str("");
4138   if (u.user && (u.pass || u.host)) {
4139     size_t n = u.pass ? u.pass - u.user - 1 : u.host - u.user - 1;
4140     s = mg_str_n(url + u.user, n);
4141   }
4142   return s;
4143 }
4144
4145 struct mg_str mg_url_pass(const char *url) {
4146   struct url u = urlparse(url);
4147   struct mg_str s = mg_str_n("", 0UL);
4148   if (u.pass && u.host) {
4149     size_t n = u.host - u.pass - 1;
4150     s = mg_str_n(url + u.pass, n);
4151   }
4152   return s;
4153 }
4154
4155 #ifdef MG_ENABLE_LINES
4156 #line 1 "src/util.c"
4157 #endif
4158
4159
4160
4161
4162 #if MG_ARCH == MG_ARCH_UNIX && defined(__APPLE__)
4163 #include <mach/mach_time.h>
4164 #endif
4165
4166 char *mg_file_read(const char *path, size_t *sizep) {
4167   FILE *fp;
4168   char *data = NULL;
4169   size_t size = 0;
4170   if ((fp = fopen(path, "rb")) != NULL) {
4171     fseek(fp, 0, SEEK_END);
4172     size = (size_t) ftell(fp);
4173     rewind(fp);
4174     data = (char *) calloc(1, size + 1);
4175     if (data != NULL) {
4176       if (fread(data, 1, size, fp) != size) {
4177         free(data);
4178         data = NULL;
4179       } else {
4180         data[size] = '\0';
4181         if (sizep != NULL) *sizep = size;
4182       }
4183     }
4184     fclose(fp);
4185   }
4186   return data;
4187 }
4188
4189 bool mg_file_write(const char *path, const void *buf, size_t len) {
4190   bool result = false;
4191   FILE *fp;
4192   char tmp[MG_PATH_MAX];
4193   snprintf(tmp, sizeof(tmp), "%s.%d", path, rand());
4194   fp = fopen(tmp, "wb");
4195   if (fp != NULL) {
4196     result = fwrite(buf, 1, len, fp) == len;
4197     fclose(fp);
4198     if (result) {
4199       remove(path);
4200       rename(tmp, path);
4201     } else {
4202       remove(tmp);
4203     }
4204   }
4205   return result;
4206 }
4207
4208 bool mg_file_printf(const char *path, const char *fmt, ...) {
4209   char tmp[256], *buf = tmp;
4210   bool result;
4211   int len;
4212   va_list ap;
4213   va_start(ap, fmt);
4214   len = mg_vasprintf(&buf, sizeof(tmp), fmt, ap);
4215   va_end(ap);
4216   result = mg_file_write(path, buf, len > 0 ? (size_t) len : 0);
4217   if (buf != tmp) free(buf);
4218   return result;
4219 }
4220
4221 #if MG_ENABLE_CUSTOM_RANDOM
4222 #else
4223 void mg_random(void *buf, size_t len) {
4224   bool done = false;
4225   unsigned char *p = (unsigned char *) buf;
4226 #if MG_ARCH == MG_ARCH_ESP32
4227   while (len--) *p++ = (unsigned char) (esp_random() & 255);
4228   done = true;
4229 #elif MG_ARCH == MG_ARCH_WIN32
4230 #elif MG_ARCH_UNIX
4231   FILE *fp = fopen("/dev/urandom", "rb");
4232   if (fp != NULL) {
4233     if (fread(buf, 1, len, fp) == len) done = true;
4234     fclose(fp);
4235   }
4236 #endif
4237   // If everything above did not work, fallback to a pseudo random generator
4238   while (!done && len--) *p++ = (unsigned char) (rand() & 255);
4239 }
4240 #endif
4241
4242 bool mg_globmatch(const char *s1, size_t n1, const char *s2, size_t n2) {
4243   size_t i = 0, j = 0, ni = 0, nj = 0;
4244   while (i < n1 || j < n2) {
4245     if (i < n1 && j < n2 && (s1[i] == '?' || s2[j] == s1[i])) {
4246       i++, j++;
4247     } else if (i < n1 && (s1[i] == '*' || s1[i] == '#')) {
4248       ni = i, nj = j + 1, i++;
4249     } else if (nj > 0 && nj <= n2 && (s1[ni] == '#' || s2[j] != '/')) {
4250       i = ni, j = nj;
4251     } else {
4252       // printf(">>: [%s] [%s] %d %d %d %d\n", s1, s2, i, j, ni, nj);
4253       return false;
4254     }
4255   }
4256   return true;
4257 }
4258
4259 static size_t mg_nce(const char *s, size_t n, size_t ofs, size_t *koff,
4260                      size_t *klen, size_t *voff, size_t *vlen) {
4261   size_t kvlen, kl;
4262   for (kvlen = 0; ofs + kvlen < n && s[ofs + kvlen] != ',';) kvlen++;
4263   for (kl = 0; kl < kvlen && s[ofs + kl] != '=';) kl++;
4264   if (koff != NULL) *koff = ofs;
4265   if (klen != NULL) *klen = kl;
4266   if (voff != NULL) *voff = kl < kvlen ? ofs + kl + 1 : 0;
4267   if (vlen != NULL) *vlen = kl < kvlen ? kvlen - kl - 1 : 0;
4268   ofs += kvlen + 1;
4269   return ofs > n ? n : ofs;
4270 }
4271
4272 bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v) {
4273   size_t koff = 0, klen = 0, voff = 0, vlen = 0;
4274   size_t off = mg_nce(s->ptr, s->len, 0, &koff, &klen, &voff, &vlen);
4275   if (k != NULL) *k = mg_str_n(s->ptr + koff, klen);
4276   if (v != NULL) *v = mg_str_n(s->ptr + voff, vlen);
4277   *s = mg_str_n(s->ptr + off, s->len - off);
4278   return off > 0;
4279 }
4280
4281 uint32_t mg_ntohl(uint32_t net) {
4282   uint8_t data[4] = {0, 0, 0, 0};
4283   memcpy(&data, &net, sizeof(data));
4284   return (((uint32_t) data[3]) << 0) | (((uint32_t) data[2]) << 8) |
4285          (((uint32_t) data[1]) << 16) | (((uint32_t) data[0]) << 24);
4286 }
4287
4288 uint16_t mg_ntohs(uint16_t net) {
4289   uint8_t data[2] = {0, 0};
4290   memcpy(&data, &net, sizeof(data));
4291   return (uint16_t) ((uint16_t) data[1] | (((uint16_t) data[0]) << 8));
4292 }
4293
4294 char *mg_hexdump(const void *buf, size_t len) {
4295   const unsigned char *p = (const unsigned char *) buf;
4296   size_t i, idx, n = 0, ofs = 0, dlen = len * 5 + 100;
4297   char ascii[17] = "", *dst = (char *) calloc(1, dlen);
4298   if (dst == NULL) return dst;
4299   for (i = 0; i < len; i++) {
4300     idx = i % 16;
4301     if (idx == 0) {
4302       if (i > 0 && dlen > n)
4303         n += (size_t) snprintf(dst + n, dlen - n, "  %s\n", ascii);
4304       if (dlen > n)
4305         n += (size_t) snprintf(dst + n, dlen - n, "%04x ", (int) (i + ofs));
4306     }
4307     if (dlen < n) break;
4308     n += (size_t) snprintf(dst + n, dlen - n, " %02x", p[i]);
4309     ascii[idx] = (char) (p[i] < 0x20 || p[i] > 0x7e ? '.' : p[i]);
4310     ascii[idx + 1] = '\0';
4311   }
4312   while (i++ % 16) {
4313     if (n < dlen) n += (size_t) snprintf(dst + n, dlen - n, "%s", "   ");
4314   }
4315   if (n < dlen) n += (size_t) snprintf(dst + n, dlen - n, "  %s\n", ascii);
4316   if (n > dlen - 1) n = dlen - 1;
4317   dst[n] = '\0';
4318   return dst;
4319 }
4320
4321 char *mg_hex(const void *buf, size_t len, char *to) {
4322   const unsigned char *p = (const unsigned char *) buf;
4323   static const char *hex = "0123456789abcdef";
4324   size_t i = 0;
4325   for (; len--; p++) {
4326     to[i++] = hex[p[0] >> 4];
4327     to[i++] = hex[p[0] & 0x0f];
4328   }
4329   to[i] = '\0';
4330   return to;
4331 }
4332
4333 static unsigned char mg_unhex_nimble(unsigned char c) {
4334   return (c >= '0' && c <= '9')   ? (unsigned char) (c - '0')
4335          : (c >= 'A' && c <= 'F') ? (unsigned char) (c - '7')
4336                                   : (unsigned char) (c - 'W');
4337 }
4338
4339 unsigned long mg_unhexn(const char *s, size_t len) {
4340   unsigned long i = 0, v = 0;
4341   for (i = 0; i < len; i++) v <<= 4, v |= mg_unhex_nimble(((uint8_t *) s)[i]);
4342   return v;
4343 }
4344
4345 void mg_unhex(const char *buf, size_t len, unsigned char *to) {
4346   size_t i;
4347   for (i = 0; i < len; i += 2) {
4348     to[i >> 1] = (unsigned char) mg_unhexn(&buf[i], 2);
4349   }
4350 }
4351
4352 int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap) {
4353   va_list ap_copy;
4354   int len;
4355
4356   va_copy(ap_copy, ap);
4357   len = vsnprintf(*buf, size, fmt, ap_copy);
4358   va_end(ap_copy);
4359
4360   if (len < 0) {
4361     // eCos and Windows are not standard-compliant and return -1 when
4362     // the buffer is too small. Keep allocating larger buffers until we
4363     // succeed or out of memory.
4364     // LCOV_EXCL_START
4365     *buf = NULL;
4366     while (len < 0) {
4367       free(*buf);
4368       if (size == 0) size = 5;
4369       size *= 2;
4370       if ((*buf = (char *) calloc(1, size)) == NULL) {
4371         len = -1;
4372         break;
4373       }
4374       va_copy(ap_copy, ap);
4375       len = vsnprintf(*buf, size - 1, fmt, ap_copy);
4376       va_end(ap_copy);
4377     }
4378     // Microsoft version of vsnprintf() is not always null-terminated, so put
4379     // the terminator manually
4380     if (*buf != NULL) (*buf)[len] = 0;
4381     // LCOV_EXCL_STOP
4382   } else if (len >= (int) size) {
4383     /// Standard-compliant code path. Allocate a buffer that is large enough
4384     if ((*buf = (char *) calloc(1, (size_t) len + 1)) == NULL) {
4385       len = -1;  // LCOV_EXCL_LINE
4386     } else {     // LCOV_EXCL_LINE
4387       va_copy(ap_copy, ap);
4388       len = vsnprintf(*buf, (size_t) len + 1, fmt, ap_copy);
4389       va_end(ap_copy);
4390     }
4391   }
4392
4393   return len;
4394 }
4395
4396 int mg_asprintf(char **buf, size_t size, const char *fmt, ...) {
4397   int ret;
4398   va_list ap;
4399   va_start(ap, fmt);
4400   ret = mg_vasprintf(buf, size, fmt, ap);
4401   va_end(ap);
4402   return ret;
4403 }
4404
4405 int64_t mg_to64(struct mg_str str) {
4406   int64_t result = 0, neg = 1, max = 922337203685477570 /* INT64_MAX/10-10 */;
4407   size_t i = 0;
4408   while (i < str.len && (str.ptr[i] == ' ' || str.ptr[i] == '\t')) i++;
4409   if (i < str.len && str.ptr[i] == '-') neg = -1, i++;
4410   while (i < str.len && str.ptr[i] >= '0' && str.ptr[i] <= '9') {
4411     if (result > max) return 0;
4412     result *= 10;
4413     result += (str.ptr[i] - '0');
4414     i++;
4415   }
4416   return result * neg;
4417 }
4418
4419 uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) {
4420   int i;
4421   crc = ~crc;
4422   while (len--) {
4423     crc ^= *(unsigned char *) buf++;
4424     for (i = 0; i < 8; i++) crc = crc & 1 ? (crc >> 1) ^ 0xedb88320 : crc >> 1;
4425   }
4426   return ~crc;
4427 }
4428
4429 static int isbyte(int n) {
4430   return n >= 0 && n <= 255;
4431 }
4432
4433 static int parse_net(const char *spec, uint32_t *net, uint32_t *mask) {
4434   int n, a, b, c, d, slash = 32, len = 0;
4435   if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 ||
4436        sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) &&
4437       isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0 &&
4438       slash < 33) {
4439     len = n;
4440     *net = ((uint32_t) a << 24) | ((uint32_t) b << 16) | ((uint32_t) c << 8) |
4441            (uint32_t) d;
4442     *mask = slash ? (uint32_t) (0xffffffffU << (32 - slash)) : (uint32_t) 0;
4443   }
4444   return len;
4445 }
4446
4447 int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip) {
4448   struct mg_str k, v;
4449   int allowed = acl.len == 0 ? '+' : '-';  // If any ACL is set, deny by default
4450   while (mg_commalist(&acl, &k, &v)) {
4451     uint32_t net, mask;
4452     if (k.ptr[0] != '+' && k.ptr[0] != '-') return -1;
4453     if (parse_net(&k.ptr[1], &net, &mask) == 0) return -2;
4454     if ((remote_ip & mask) == net) allowed = k.ptr[0];
4455   }
4456   return allowed == '+';
4457 }
4458
4459 double mg_time(void) {
4460 #if MG_ARCH == MG_ARCH_WIN32
4461   SYSTEMTIME sysnow;
4462   FILETIME ftime;
4463   GetLocalTime(&sysnow);
4464   SystemTimeToFileTime(&sysnow, &ftime);
4465   /*
4466    * 1. VC 6.0 doesn't support conversion uint64 -> double, so, using int64
4467    * This should not cause a problems in this (21th) century
4468    * 2. Windows FILETIME is a number of 100-nanosecond intervals since January
4469    * 1, 1601 while time_t is a number of _seconds_ since January 1, 1970 UTC,
4470    * thus, we need to convert to seconds and adjust amount (subtract 11644473600
4471    * seconds)
4472    */
4473   return (double) (((int64_t) ftime.dwLowDateTime +
4474                     ((int64_t) ftime.dwHighDateTime << 32)) /
4475                    10000000.0) -
4476          11644473600;
4477 #elif MG_ARCH == MG_ARCH_FREERTOS_TCP || MG_ARCH == MG_ARCH_AZURERTOS
4478   return mg_millis() / 1000.0;
4479 #else
4480   struct timeval tv;
4481   if (gettimeofday(&tv, NULL /* tz */) != 0) return 0;
4482   return (double) tv.tv_sec + (((double) tv.tv_usec) / 1000000.0);
4483 #endif /* _WIN32 */
4484 }
4485
4486 void mg_usleep(unsigned long usecs) {
4487 #if MG_ARCH == MG_ARCH_WIN32
4488   Sleep(usecs / 1000);
4489 #elif MG_ARCH == MG_ARCH_ESP8266
4490   ets_delay_us(usecs);
4491 #elif MG_ARCH == MG_ARCH_FREERTOS_TCP || MG_ARCH == MG_ARCH_FREERTOS_LWIP
4492   vTaskDelay(pdMS_TO_TICKS(usecs / 1000));
4493 #elif MG_ARCH == MG_ARCH_AZURERTOS
4494   tx_thread_sleep((usecs / 1000) * TX_TIMER_TICKS_PER_SECOND);
4495 #else
4496   usleep((useconds_t) usecs);
4497 #endif
4498 }
4499
4500 unsigned long mg_millis(void) {
4501 #if MG_ARCH == MG_ARCH_WIN32
4502   return GetTickCount();
4503 #elif MG_ARCH == MG_ARCH_ESP32
4504   return esp_timer_get_time() / 1000;
4505 #elif MG_ARCH == MG_ARCH_ESP8266
4506   return xTaskGetTickCount() * portTICK_PERIOD_MS;
4507 #elif MG_ARCH == MG_ARCH_FREERTOS_TCP || MG_ARCH == MG_ARCH_FREERTOS_LWIP
4508   return xTaskGetTickCount() * portTICK_PERIOD_MS;
4509 #elif MG_ARCH == MG_ARCH_AZURERTOS
4510   return tx_time_get() * (1000 /* MS per SEC */ / TX_TIMER_TICKS_PER_SECOND);
4511 #elif MG_ARCH == MG_ARCH_UNIX && defined(__APPLE__)
4512   uint64_t ticks = mach_absolute_time();
4513   static mach_timebase_info_data_t timebase;
4514   mach_timebase_info(&timebase);
4515   double ticks_to_nanos = (double)timebase.numer / timebase.denom;
4516   uint64_t uptime_nanos = (uint64_t)(ticks_to_nanos * ticks);
4517   return (unsigned long) (uptime_nanos / 1000000);
4518 #else
4519   struct timespec ts;
4520 #ifdef _POSIX_MONOTONIC_CLOCK
4521 #ifdef CLOCK_MONOTONIC_RAW
4522   clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
4523 #else
4524   clock_gettime(CLOCK_MONOTONIC, &ts);
4525 #endif
4526 #else
4527   clock_gettime(CLOCK_REALTIME, &ts);
4528 #endif
4529   return (unsigned long) ((uint64_t) ts.tv_sec * 1000 +
4530                           (uint64_t) ts.tv_nsec / 1000000);
4531 #endif
4532 }
4533
4534 #ifdef MG_ENABLE_LINES
4535 #line 1 "src/ws.c"
4536 #endif
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546 struct ws_msg {
4547   uint8_t flags;
4548   size_t header_len;
4549   size_t data_len;
4550 };
4551
4552 static void ws_handshake(struct mg_connection *c, const struct mg_str *wskey,
4553                          const struct mg_str *wsproto, const char *fmt,
4554                          va_list ap) {
4555   const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
4556   unsigned char sha[20], b64_sha[30];
4557   char mem[128], *buf = mem;
4558
4559   mg_sha1_ctx sha_ctx;
4560   mg_sha1_init(&sha_ctx);
4561   mg_sha1_update(&sha_ctx, (unsigned char *) wskey->ptr, wskey->len);
4562   mg_sha1_update(&sha_ctx, (unsigned char *) magic, 36);
4563   mg_sha1_final(sha, &sha_ctx);
4564   mg_base64_encode(sha, sizeof(sha), (char *) b64_sha);
4565   buf[0] = '\0';
4566   if (fmt != NULL) mg_vasprintf(&buf, sizeof(mem), fmt, ap);
4567   mg_printf(c,
4568             "HTTP/1.1 101 Switching Protocols\r\n"
4569             "Upgrade: websocket\r\n"
4570             "Connection: Upgrade\r\n"
4571             "Sec-WebSocket-Accept: %s\r\n"
4572             "%s",
4573             b64_sha, buf);
4574   if (buf != mem) free(buf);
4575   if (wsproto != NULL) {
4576     mg_printf(c, "Sec-WebSocket-Protocol: %.*s\r\n", (int) wsproto->len,
4577               wsproto->ptr);
4578   }
4579   mg_send(c, "\r\n", 2);
4580 }
4581
4582 static size_t ws_process(uint8_t *buf, size_t len, struct ws_msg *msg) {
4583   size_t i, n = 0, mask_len = 0;
4584   memset(msg, 0, sizeof(*msg));
4585   if (len >= 2) {
4586     n = buf[1] & 0x7f;                // Frame length
4587     mask_len = buf[1] & 128 ? 4 : 0;  // last bit is a mask bit
4588     msg->flags = buf[0];
4589     if (n < 126 && len >= mask_len) {
4590       msg->data_len = n;
4591       msg->header_len = 2 + mask_len;
4592     } else if (n == 126 && len >= 4 + mask_len) {
4593       msg->header_len = 4 + mask_len;
4594       msg->data_len = mg_ntohs(*(uint16_t *) &buf[2]);
4595     } else if (len >= 10 + mask_len) {
4596       msg->header_len = 10 + mask_len;
4597       msg->data_len =
4598           (size_t) (((uint64_t) mg_ntohl(*(uint32_t *) &buf[2])) << 32) +
4599           mg_ntohl(*(uint32_t *) &buf[6]);
4600     }
4601   }
4602   // Sanity check, and integer overflow protection for the boundary check below
4603   // data_len should not be larger than 1 Gb
4604   if (msg->data_len > 1024 * 1024 * 1024) return 0;
4605   if (msg->header_len + msg->data_len > len) return 0;
4606   if (mask_len > 0) {
4607     uint8_t *p = buf + msg->header_len, *m = p - mask_len;
4608     for (i = 0; i < msg->data_len; i++) p[i] ^= m[i & 3];
4609   }
4610   return msg->header_len + msg->data_len;
4611 }
4612
4613 static size_t mkhdr(size_t len, int op, bool is_client, uint8_t *buf) {
4614   size_t n = 0;
4615   buf[0] = (uint8_t) (op | 128);
4616   if (len < 126) {
4617     buf[1] = (unsigned char) len;
4618     n = 2;
4619   } else if (len < 65536) {
4620     uint16_t tmp = mg_htons((uint16_t) len);
4621     buf[1] = 126;
4622     memcpy(&buf[2], &tmp, sizeof(tmp));
4623     n = 4;
4624   } else {
4625     uint32_t tmp;
4626     buf[1] = 127;
4627     tmp = mg_htonl((uint32_t) ((uint64_t) len >> 32));
4628     memcpy(&buf[2], &tmp, sizeof(tmp));
4629     tmp = mg_htonl((uint32_t) (len & 0xffffffff));
4630     memcpy(&buf[6], &tmp, sizeof(tmp));
4631     n = 10;
4632   }
4633   if (is_client) {
4634     buf[1] |= 1 << 7;  // Set masking flag
4635     mg_random(&buf[n], 4);
4636     n += 4;
4637   }
4638   return n;
4639 }
4640
4641 static void mg_ws_mask(struct mg_connection *c, size_t len) {
4642   if (c->is_client && c->send.buf != NULL) {
4643     size_t i;
4644     uint8_t *p = c->send.buf + c->send.len - len, *mask = p - 4;
4645     for (i = 0; i < len; i++) p[i] ^= mask[i & 3];
4646   }
4647 }
4648
4649 size_t mg_ws_send(struct mg_connection *c, const char *buf, size_t len,
4650                   int op) {
4651   uint8_t header[14];
4652   size_t header_len = mkhdr(len, op, c->is_client, header);
4653   mg_send(c, header, header_len);
4654   LOG(LL_VERBOSE_DEBUG, ("WS out: %d [%.*s]", (int) len, (int) len, buf));
4655   mg_send(c, buf, len);
4656   mg_ws_mask(c, len);
4657   return header_len + len;
4658 }
4659
4660 static void mg_ws_cb(struct mg_connection *c, int ev, void *ev_data,
4661                      void *fn_data) {
4662   struct ws_msg msg;
4663   size_t ofs = (size_t) c->pfn_data;
4664
4665   // assert(ofs < c->recv.len);
4666   if (ev == MG_EV_READ) {
4667     if (!c->is_websocket && c->is_client) {
4668       int n = mg_http_get_request_len(c->recv.buf, c->recv.len);
4669       if (n < 0) {
4670         c->is_closing = 1;  // Some just, not an HTTP request
4671       } else if (n > 0) {
4672         if (n < 15 || memcmp(c->recv.buf + 9, "101", 3) != 0) {
4673           LOG(LL_ERROR,
4674               ("%lu WS handshake error: %.*s", c->id, 15, c->recv.buf));
4675           c->is_closing = 1;
4676         } else {
4677           struct mg_http_message hm;
4678           mg_http_parse((char *) c->recv.buf, c->recv.len, &hm);
4679           c->is_websocket = 1;
4680           mg_call(c, MG_EV_WS_OPEN, &hm);
4681         }
4682         mg_iobuf_del(&c->recv, 0, (size_t) n);
4683       } else {
4684         return;  // A request is not yet received
4685       }
4686     }
4687
4688     while (ws_process(c->recv.buf + ofs, c->recv.len - ofs, &msg) > 0) {
4689       char *s = (char *) c->recv.buf + ofs + msg.header_len;
4690       struct mg_ws_message m = {{s, msg.data_len}, msg.flags};
4691       size_t len = msg.header_len + msg.data_len;
4692       uint8_t final = msg.flags & 128, op = msg.flags & 15;
4693       // LOG(LL_VERBOSE_DEBUG, ("fin %d op %d len %d [%.*s]", final, op,
4694       //                       (int) m.data.len, (int) m.data.len, m.data.ptr));
4695       switch (op) {
4696         case WEBSOCKET_OP_CONTINUE:
4697           mg_call(c, MG_EV_WS_CTL, &m);
4698           break;
4699         case WEBSOCKET_OP_PING:
4700           LOG(LL_DEBUG, ("%s", "WS PONG"));
4701           mg_ws_send(c, s, msg.data_len, WEBSOCKET_OP_PONG);
4702           mg_call(c, MG_EV_WS_CTL, &m);
4703           break;
4704         case WEBSOCKET_OP_PONG:
4705           mg_call(c, MG_EV_WS_CTL, &m);
4706           break;
4707         case WEBSOCKET_OP_TEXT:
4708         case WEBSOCKET_OP_BINARY:
4709           if (final) mg_call(c, MG_EV_WS_MSG, &m);
4710           break;
4711         case WEBSOCKET_OP_CLOSE:
4712           LOG(LL_ERROR, ("%lu Got WS CLOSE", c->id));
4713           mg_call(c, MG_EV_WS_CTL, &m);
4714           c->is_closing = 1;
4715           break;
4716         default:
4717           // Per RFC6455, close conn when an unknown op is recvd
4718           mg_error(c, "unknown WS op %d", op);
4719           break;
4720       }
4721
4722       // Handle fragmented frames: strip header, keep in c->recv
4723       if (final == 0 || op == 0) {
4724         if (op) ofs++, len--, msg.header_len--;       // First frame
4725         mg_iobuf_del(&c->recv, ofs, msg.header_len);  // Strip header
4726         len -= msg.header_len;
4727         ofs += len;
4728         c->pfn_data = (void *) ofs;
4729         // LOG(LL_INFO, ("FRAG %d [%.*s]", (int) ofs, (int) ofs, c->recv.buf));
4730       }
4731       // Remove non-fragmented frame
4732       if (final && op) mg_iobuf_del(&c->recv, ofs, len);
4733       // Last chunk of the fragmented frame
4734       if (final && !op) {
4735         m.flags = c->recv.buf[0];
4736         m.data = mg_str_n((char *) &c->recv.buf[1], (size_t) (ofs - 1));
4737         mg_call(c, MG_EV_WS_MSG, &m);
4738         mg_iobuf_del(&c->recv, 0, ofs);
4739         ofs = 0;
4740         c->pfn_data = NULL;
4741       }
4742     }
4743   }
4744   (void) fn_data;
4745   (void) ev_data;
4746 }
4747
4748 struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url,
4749                                     mg_event_handler_t fn, void *fn_data,
4750                                     const char *fmt, ...) {
4751   struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
4752   if (c != NULL) {
4753     char nonce[16], key[30], mem1[128], mem2[256], *buf1 = mem1, *buf2 = mem2;
4754     struct mg_str host = mg_url_host(url);
4755     int n1 = 0, n2 = 0;
4756     if (fmt != NULL) {
4757       va_list ap;
4758       va_start(ap, fmt);
4759       n1 = mg_vasprintf(&buf1, sizeof(mem1), fmt, ap);
4760       va_end(ap);
4761     }
4762     // Send handshake request
4763     // mg_url_host(url, host, sizeof(host));
4764     mg_random(nonce, sizeof(nonce));
4765     mg_base64_encode((unsigned char *) nonce, sizeof(nonce), key);
4766     // LOG(LL_DEBUG, "%p [%s]", uri, uri == NULL ? "???" : uri);
4767     n2 = mg_asprintf(&buf2, sizeof(mem2),
4768                      "GET %s HTTP/1.1\r\n"
4769                      "Upgrade: websocket\r\n"
4770                      "Host: %.*s\r\n"
4771                      "Connection: Upgrade\r\n"
4772                      "%.*s"
4773                      "Sec-WebSocket-Version: 13\r\n"
4774                      "Sec-WebSocket-Key: %s\r\n"
4775                      "\r\n",
4776                      mg_url_uri(url), (int) host.len, host.ptr, n1, buf1, key);
4777     mg_send(c, buf2, n2 > 0 ? (size_t) n2 : 0);
4778     if (buf1 != mem1) free(buf1);
4779     if (buf2 != mem2) free(buf2);
4780     c->pfn = mg_ws_cb;
4781     c->pfn_data = NULL;
4782   }
4783   return c;
4784 }
4785
4786 void mg_ws_upgrade(struct mg_connection *c, struct mg_http_message *hm,
4787                    const char *fmt, ...) {
4788   struct mg_str *wskey = mg_http_get_header(hm, "Sec-WebSocket-Key");
4789   c->pfn = mg_ws_cb;
4790   c->pfn_data = NULL;
4791   if (wskey == NULL) {
4792     mg_http_reply(c, 426, "", "WS upgrade expected\n");
4793     c->is_draining = 1;
4794   } else {
4795     struct mg_str *wsproto = mg_http_get_header(hm, "Sec-WebSocket-Protocol");
4796     va_list ap;
4797     va_start(ap, fmt);
4798     ws_handshake(c, wskey, wsproto, fmt, ap);
4799     va_end(ap);
4800     c->is_websocket = 1;
4801     mg_call(c, MG_EV_WS_OPEN, hm);
4802   }
4803 }
4804
4805 size_t mg_ws_wrap(struct mg_connection *c, size_t len, int op) {
4806   uint8_t header[14], *p;
4807   size_t header_len = mkhdr(len, op, c->is_client, header);
4808
4809   // NOTE: order of operations is important!
4810   mg_iobuf_add(&c->send, c->send.len, NULL, header_len, MG_IO_SIZE);
4811   p = &c->send.buf[c->send.len - len];         // p points to data
4812   memmove(p, p - header_len, len);             // Shift data
4813   memcpy(p - header_len, header, header_len);  // Prepend header
4814   mg_ws_mask(c, len);                          // Mask data
4815
4816   return c->send.len;
4817 }