]> gitweb.ps.run Git - matrix_esp_thesis/blob - ext/mongoose/mongoose.c
clean up
[matrix_esp_thesis] / ext / mongoose / mongoose.c
1 // Copyright (c) 2004-2013 Sergey Lyubka
2 // Copyright (c) 2013-2022 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 // SPDX-License-Identifier: GPL-2.0-only or commercial
19
20 #include "mongoose.h"
21
22 #ifdef MG_ENABLE_LINES
23 #line 1 "src/base64.c"
24 #endif
25
26
27
28 static int mg_b64idx(int c) {
29   if (c < 26) {
30     return c + 'A';
31   } else if (c < 52) {
32     return c - 26 + 'a';
33   } else if (c < 62) {
34     return c - 52 + '0';
35   } else {
36     return c == 62 ? '+' : '/';
37   }
38 }
39
40 static int mg_b64rev(int c) {
41   if (c >= 'A' && c <= 'Z') {
42     return c - 'A';
43   } else if (c >= 'a' && c <= 'z') {
44     return c + 26 - 'a';
45   } else if (c >= '0' && c <= '9') {
46     return c + 52 - '0';
47   } else if (c == '+') {
48     return 62;
49   } else if (c == '/') {
50     return 63;
51   } else if (c == '=') {
52     return 64;
53   } else {
54     return -1;
55   }
56 }
57
58 int mg_base64_update(unsigned char ch, char *to, int n) {
59   int rem = (n & 3) % 3;
60   if (rem == 0) {
61     to[n] = (char) mg_b64idx(ch >> 2);
62     to[++n] = (char) ((ch & 3) << 4);
63   } else if (rem == 1) {
64     to[n] = (char) mg_b64idx(to[n] | (ch >> 4));
65     to[++n] = (char) ((ch & 15) << 2);
66   } else {
67     to[n] = (char) mg_b64idx(to[n] | (ch >> 6));
68     to[++n] = (char) mg_b64idx(ch & 63);
69     n++;
70   }
71   return n;
72 }
73
74 int mg_base64_final(char *to, int n) {
75   int saved = n;
76   // printf("---[%.*s]\n", n, to);
77   if (n & 3) n = mg_base64_update(0, to, n);
78   if ((saved & 3) == 2) n--;
79   // printf("    %d[%.*s]\n", n, n, to);
80   while (n & 3) to[n++] = '=';
81   to[n] = '\0';
82   return n;
83 }
84
85 int mg_base64_encode(const unsigned char *p, int n, char *to) {
86   int i, len = 0;
87   for (i = 0; i < n; i++) len = mg_base64_update(p[i], to, len);
88   len = mg_base64_final(to, len);
89   return len;
90 }
91
92 int mg_base64_decode(const char *src, int n, char *dst) {
93   const char *end = src == NULL ? NULL : src + n;  // Cannot add to NULL
94   int len = 0;
95   while (src != NULL && src + 3 < end) {
96     int a = mg_b64rev(src[0]), b = mg_b64rev(src[1]), c = mg_b64rev(src[2]),
97         d = mg_b64rev(src[3]);
98     if (a == 64 || a < 0 || b == 64 || b < 0 || c < 0 || d < 0) return 0;
99     dst[len++] = (char) ((a << 2) | (b >> 4));
100     if (src[2] != '=') {
101       dst[len++] = (char) ((b << 4) | (c >> 2));
102       if (src[3] != '=') dst[len++] = (char) ((c << 6) | d);
103     }
104     src += 4;
105   }
106   dst[len] = '\0';
107   return len;
108 }
109
110 #ifdef MG_ENABLE_LINES
111 #line 1 "src/dns.c"
112 #endif
113
114
115
116
117
118
119
120
121 struct dns_data {
122   struct dns_data *next;
123   struct mg_connection *c;
124   uint64_t expire;
125   uint16_t txnid;
126 };
127
128 static void mg_sendnsreq(struct mg_connection *, struct mg_str *, int,
129                          struct mg_dns *, bool);
130
131 static void mg_dns_free(struct mg_connection *c, struct dns_data *d) {
132   LIST_DELETE(struct dns_data,
133               (struct dns_data **) &c->mgr->active_dns_requests, d);
134   free(d);
135 }
136
137 void mg_resolve_cancel(struct mg_connection *c) {
138   struct dns_data *tmp, *d = (struct dns_data *) c->mgr->active_dns_requests;
139   for (; d != NULL; d = tmp) {
140     tmp = d->next;
141     if (d->c == c) mg_dns_free(c, d);
142   }
143 }
144
145 static size_t mg_dns_parse_name_depth(const uint8_t *s, size_t len, size_t ofs,
146                                       char *to, size_t tolen, size_t j,
147                                       int depth) {
148   size_t i = 0;
149   if (tolen > 0 && depth == 0) to[0] = '\0';
150   if (depth > 5) return 0;
151   // MG_INFO(("ofs %lx %x %x", (unsigned long) ofs, s[ofs], s[ofs + 1]));
152   while (ofs + i + 1 < len) {
153     size_t n = s[ofs + i];
154     if (n == 0) {
155       i++;
156       break;
157     }
158     if (n & 0xc0) {
159       size_t ptr = (((n & 0x3f) << 8) | s[ofs + i + 1]);  // 12 is hdr len
160       // MG_INFO(("PTR %lx", (unsigned long) ptr));
161       if (ptr + 1 < len && (s[ptr] & 0xc0) == 0 &&
162           mg_dns_parse_name_depth(s, len, ptr, to, tolen, j, depth + 1) == 0)
163         return 0;
164       i += 2;
165       break;
166     }
167     if (ofs + i + n + 1 >= len) return 0;
168     if (j > 0) {
169       if (j < tolen) to[j] = '.';
170       j++;
171     }
172     if (j + n < tolen) memcpy(&to[j], &s[ofs + i + 1], n);
173     j += n;
174     i += n + 1;
175     if (j < tolen) to[j] = '\0';  // Zero-terminate this chunk
176     // MG_INFO(("--> [%s]", to));
177   }
178   if (tolen > 0) to[tolen - 1] = '\0';  // Make sure make sure it is nul-term
179   return i;
180 }
181
182 static size_t mg_dns_parse_name(const uint8_t *s, size_t n, size_t ofs,
183                                 char *dst, size_t dstlen) {
184   return mg_dns_parse_name_depth(s, n, ofs, dst, dstlen, 0, 0);
185 }
186
187 size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
188                        bool is_question, struct mg_dns_rr *rr) {
189   const uint8_t *s = buf + ofs, *e = &buf[len];
190
191   memset(rr, 0, sizeof(*rr));
192   if (len < sizeof(struct mg_dns_header)) return 0;  // Too small
193   if (len > 512) return 0;  //  Too large, we don't expect that
194   if (s >= e) return 0;     //  Overflow
195
196   if ((rr->nlen = (uint16_t) mg_dns_parse_name(buf, len, ofs, NULL, 0)) == 0)
197     return 0;
198   s += rr->nlen + 4;
199   if (s > e) return 0;
200   rr->atype = (uint16_t) (((uint16_t) s[-4] << 8) | s[-3]);
201   rr->aclass = (uint16_t) (((uint16_t) s[-2] << 8) | s[-1]);
202   if (is_question) return (size_t) (rr->nlen + 4);
203
204   s += 6;
205   if (s > e) return 0;
206   rr->alen = (uint16_t) (((uint16_t) s[-2] << 8) | s[-1]);
207   if (s + rr->alen > e) return 0;
208   return (size_t) (rr->nlen + rr->alen + 10);
209 }
210
211 bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
212   const struct mg_dns_header *h = (struct mg_dns_header *) buf;
213   struct mg_dns_rr rr;
214   size_t i, n, ofs = sizeof(*h);
215   memset(dm, 0, sizeof(*dm));
216
217   if (len < sizeof(*h)) return 0;                // Too small, headers dont fit
218   if (mg_ntohs(h->num_questions) > 1) return 0;  // Sanity
219   if (mg_ntohs(h->num_answers) > 10) return 0;   // Sanity
220   dm->txnid = mg_ntohs(h->txnid);
221
222   for (i = 0; i < mg_ntohs(h->num_questions); i++) {
223     if ((n = mg_dns_parse_rr(buf, len, ofs, true, &rr)) == 0) return false;
224     // MG_INFO(("Q %lu %lu %hu/%hu", ofs, n, rr.atype, rr.aclass));
225     ofs += n;
226   }
227   for (i = 0; i < mg_ntohs(h->num_answers); i++) {
228     if ((n = mg_dns_parse_rr(buf, len, ofs, false, &rr)) == 0) return false;
229     // MG_INFO(("A -- %lu %lu %hu/%hu %s", ofs, n, rr.atype, rr.aclass,
230     // dm->name));
231     mg_dns_parse_name(buf, len, ofs, dm->name, sizeof(dm->name));
232     ofs += n;
233
234     if (rr.alen == 4 && rr.atype == 1 && rr.aclass == 1) {
235       dm->addr.is_ip6 = false;
236       memcpy(&dm->addr.ip, &buf[ofs - 4], 4);
237       dm->resolved = true;
238       break;  // Return success
239     } else if (rr.alen == 16 && rr.atype == 28 && rr.aclass == 1) {
240       dm->addr.is_ip6 = true;
241       memcpy(&dm->addr.ip6, &buf[ofs - 16], 16);
242       dm->resolved = true;
243       break;  // Return success
244     }
245   }
246   return true;
247 }
248
249 static void dns_cb(struct mg_connection *c, int ev, void *ev_data,
250                    void *fn_data) {
251   struct dns_data *d, *tmp;
252   if (ev == MG_EV_POLL) {
253     uint64_t now = *(uint64_t *) ev_data;
254     for (d = (struct dns_data *) c->mgr->active_dns_requests; d != NULL;
255          d = tmp) {
256       tmp = d->next;
257       // MG_DEBUG ("%lu %lu dns poll", d->expire, now));
258       if (now > d->expire) mg_error(d->c, "DNS timeout");
259     }
260   } else if (ev == MG_EV_READ) {
261     struct mg_dns_message dm;
262     int resolved = 0;
263     if (mg_dns_parse(c->recv.buf, c->recv.len, &dm) == false) {
264       MG_ERROR(("Unexpected DNS response:"));
265       mg_hexdump(c->recv.buf, c->recv.len);
266     } else {
267       // MG_VERBOSE(("%s %d", dm.name, dm.resolved));
268       for (d = (struct dns_data *) c->mgr->active_dns_requests; d != NULL;
269            d = tmp) {
270         tmp = d->next;
271         // MG_INFO(("d %p %hu %hu", d, d->txnid, dm.txnid));
272         if (dm.txnid != d->txnid) continue;
273         if (d->c->is_resolving) {
274           if (dm.resolved) {
275             dm.addr.port = d->c->rem.port;  // Save port
276             d->c->rem = dm.addr;            // Copy resolved address
277             MG_DEBUG(
278                 ("%lu %s is %M", d->c->id, dm.name, mg_print_ip, &d->c->rem));
279             mg_connect_resolved(d->c);
280 #if MG_ENABLE_IPV6
281           } else if (dm.addr.is_ip6 == false && dm.name[0] != '\0' &&
282                      c->mgr->use_dns6 == false) {
283             struct mg_str x = mg_str(dm.name);
284             mg_sendnsreq(d->c, &x, c->mgr->dnstimeout, &c->mgr->dns6, true);
285 #endif
286           } else {
287             mg_error(d->c, "%s DNS lookup failed", dm.name);
288           }
289         } else {
290           MG_ERROR(("%lu already resolved", d->c->id));
291         }
292         mg_dns_free(c, d);
293         resolved = 1;
294       }
295     }
296     if (!resolved) MG_ERROR(("stray DNS reply"));
297     c->recv.len = 0;
298   } else if (ev == MG_EV_CLOSE) {
299     for (d = (struct dns_data *) c->mgr->active_dns_requests; d != NULL;
300          d = tmp) {
301       tmp = d->next;
302       mg_error(d->c, "DNS error");
303       mg_dns_free(c, d);
304     }
305   }
306   (void) fn_data;
307 }
308
309 static bool mg_dns_send(struct mg_connection *c, const struct mg_str *name,
310                         uint16_t txnid, bool ipv6) {
311   struct {
312     struct mg_dns_header header;
313     uint8_t data[256];
314   } pkt;
315   size_t i, n;
316   memset(&pkt, 0, sizeof(pkt));
317   pkt.header.txnid = mg_htons(txnid);
318   pkt.header.flags = mg_htons(0x100);
319   pkt.header.num_questions = mg_htons(1);
320   for (i = n = 0; i < sizeof(pkt.data) - 5; i++) {
321     if (name->ptr[i] == '.' || i >= name->len) {
322       pkt.data[n] = (uint8_t) (i - n);
323       memcpy(&pkt.data[n + 1], name->ptr + n, i - n);
324       n = i + 1;
325     }
326     if (i >= name->len) break;
327   }
328   memcpy(&pkt.data[n], "\x00\x00\x01\x00\x01", 5);  // A query
329   n += 5;
330   if (ipv6) pkt.data[n - 3] = 0x1c;  // AAAA query
331   // memcpy(&pkt.data[n], "\xc0\x0c\x00\x1c\x00\x01", 6);  // AAAA query
332   // n += 6;
333   return mg_send(c, &pkt, sizeof(pkt.header) + n);
334 }
335
336 static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
337                          struct mg_dns *dnsc, bool ipv6) {
338   struct dns_data *d = NULL;
339   if (dnsc->url == NULL) {
340     mg_error(c, "DNS server URL is NULL. Call mg_mgr_init()");
341   } else if (dnsc->c == NULL) {
342     dnsc->c = mg_connect(c->mgr, dnsc->url, NULL, NULL);
343     if (dnsc->c != NULL) {
344       dnsc->c->pfn = dns_cb;
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     struct dns_data *reqs = (struct dns_data *) c->mgr->active_dns_requests;
354     d->txnid = reqs ? (uint16_t) (reqs->txnid + 1) : 1;
355     d->next = (struct dns_data *) c->mgr->active_dns_requests;
356     c->mgr->active_dns_requests = d;
357     d->expire = mg_millis() + (uint64_t) ms;
358     d->c = c;
359     c->is_resolving = 1;
360     MG_VERBOSE(("%lu resolving %.*s @ %s, txnid %hu", c->id, (int) name->len,
361                 name->ptr, dnsc->url, d->txnid));
362     if (!mg_dns_send(dnsc->c, name, d->txnid, ipv6)) {
363       mg_error(dnsc->c, "DNS send");
364     }
365   }
366 }
367
368 void mg_resolve(struct mg_connection *c, const char *url) {
369   struct mg_str host = mg_url_host(url);
370   c->rem.port = mg_htons(mg_url_port(url));
371   if (mg_aton(host, &c->rem)) {
372     // host is an IP address, do not fire name resolution
373     mg_connect_resolved(c);
374   } else {
375     // host is not an IP, send DNS resolution request
376     struct mg_dns *dns = c->mgr->use_dns6 ? &c->mgr->dns6 : &c->mgr->dns4;
377     mg_sendnsreq(c, &host, c->mgr->dnstimeout, dns, c->mgr->use_dns6);
378   }
379 }
380
381 #ifdef MG_ENABLE_LINES
382 #line 1 "src/event.c"
383 #endif
384
385
386
387
388
389 void mg_call(struct mg_connection *c, int ev, void *ev_data) {
390   // Run user-defined handler first, in order to give it an ability
391   // to intercept processing (e.g. clean input buffer) before the
392   // protocol handler kicks in
393   if (c->fn != NULL) c->fn(c, ev, ev_data, c->fn_data);
394   if (c->pfn != NULL) c->pfn(c, ev, ev_data, c->pfn_data);
395 }
396
397 void mg_error(struct mg_connection *c, const char *fmt, ...) {
398   char buf[64];
399   va_list ap;
400   va_start(ap, fmt);
401   mg_vsnprintf(buf, sizeof(buf), fmt, &ap);
402   va_end(ap);
403   MG_ERROR(("%lu %p %s", c->id, c->fd, buf));
404   c->is_closing = 1;             // Set is_closing before sending MG_EV_CALL
405   mg_call(c, MG_EV_ERROR, buf);  // Let user handler to override it
406 }
407
408 #ifdef MG_ENABLE_LINES
409 #line 1 "src/fmt.c"
410 #endif
411
412
413
414
415 static bool is_digit(int c) {
416   return c >= '0' && c <= '9';
417 }
418
419 static int addexp(char *buf, int e, int sign) {
420   int n = 0;
421   buf[n++] = 'e';
422   buf[n++] = (char) sign;
423   if (e > 400) return 0;
424   if (e < 10) buf[n++] = '0';
425   if (e >= 100) buf[n++] = (char) (e / 100 + '0'), e -= 100 * (e / 100);
426   if (e >= 10) buf[n++] = (char) (e / 10 + '0'), e -= 10 * (e / 10);
427   buf[n++] = (char) (e + '0');
428   return n;
429 }
430
431 static int xisinf(double x) {
432   union {
433     double f;
434     uint64_t u;
435   } ieee754 = {x};
436   return ((unsigned) (ieee754.u >> 32) & 0x7fffffff) == 0x7ff00000 &&
437          ((unsigned) ieee754.u == 0);
438 }
439
440 static int xisnan(double x) {
441   union {
442     double f;
443     uint64_t u;
444   } ieee754 = {x};
445   return ((unsigned) (ieee754.u >> 32) & 0x7fffffff) +
446              ((unsigned) ieee754.u != 0) >
447          0x7ff00000;
448 }
449
450 static size_t mg_dtoa(char *dst, size_t dstlen, double d, int width, bool tz) {
451   char buf[40];
452   int i, s = 0, n = 0, e = 0;
453   double t, mul, saved;
454   if (d == 0.0) return mg_snprintf(dst, dstlen, "%s", "0");
455   if (xisinf(d)) return mg_snprintf(dst, dstlen, "%s", d > 0 ? "inf" : "-inf");
456   if (xisnan(d)) return mg_snprintf(dst, dstlen, "%s", "nan");
457   if (d < 0.0) d = -d, buf[s++] = '-';
458
459   // Round
460   saved = d;
461   mul = 1.0;
462   while (d >= 10.0 && d / mul >= 10.0) mul *= 10.0;
463   while (d <= 1.0 && d / mul <= 1.0) mul /= 10.0;
464   for (i = 0, t = mul * 5; i < width; i++) t /= 10.0;
465   d += t;
466   // Calculate exponent, and 'mul' for scientific representation
467   mul = 1.0;
468   while (d >= 10.0 && d / mul >= 10.0) mul *= 10.0, e++;
469   while (d < 1.0 && d / mul < 1.0) mul /= 10.0, e--;
470   // printf(" --> %g %d %g %g\n", saved, e, t, mul);
471
472   if (e >= width && width > 1) {
473     n = (int) mg_dtoa(buf, sizeof(buf), saved / mul, width, tz);
474     // printf(" --> %.*g %d [%.*s]\n", 10, d / t, e, n, buf);
475     n += addexp(buf + s + n, e, '+');
476     return mg_snprintf(dst, dstlen, "%.*s", n, buf);
477   } else if (e <= -width && width > 1) {
478     n = (int) mg_dtoa(buf, sizeof(buf), saved / mul, width, tz);
479     // printf(" --> %.*g %d [%.*s]\n", 10, d / mul, e, n, buf);
480     n += addexp(buf + s + n, -e, '-');
481     return mg_snprintf(dst, dstlen, "%.*s", n, buf);
482   } else {
483     for (i = 0, t = mul; t >= 1.0 && s + n < (int) sizeof(buf); i++) {
484       int ch = (int) (d / t);
485       if (n > 0 || ch > 0) buf[s + n++] = (char) (ch + '0');
486       d -= ch * t;
487       t /= 10.0;
488     }
489     // printf(" --> [%g] -> %g %g (%d) [%.*s]\n", saved, d, t, n, s + n, buf);
490     if (n == 0) buf[s++] = '0';
491     while (t >= 1.0 && n + s < (int) sizeof(buf)) buf[n++] = '0', t /= 10.0;
492     if (s + n < (int) sizeof(buf)) buf[n + s++] = '.';
493     // printf(" 1--> [%g] -> [%.*s]\n", saved, s + n, buf);
494     for (i = 0, t = 0.1; s + n < (int) sizeof(buf) && n < width; i++) {
495       int ch = (int) (d / t);
496       buf[s + n++] = (char) (ch + '0');
497       d -= ch * t;
498       t /= 10.0;
499     }
500   }
501   while (tz && n > 0 && buf[s + n - 1] == '0') n--;  // Trim trailing zeroes
502   if (n > 0 && buf[s + n - 1] == '.') n--;           // Trim trailing dot
503   n += s;
504   if (n >= (int) sizeof(buf)) n = (int) sizeof(buf) - 1;
505   buf[n] = '\0';
506   return mg_snprintf(dst, dstlen, "%s", buf);
507 }
508
509 static size_t mg_lld(char *buf, int64_t val, bool is_signed, bool is_hex) {
510   const char *letters = "0123456789abcdef";
511   uint64_t v = (uint64_t) val;
512   size_t s = 0, n, i;
513   if (is_signed && val < 0) buf[s++] = '-', v = (uint64_t) (-val);
514   // This loop prints a number in reverse order. I guess this is because we
515   // write numbers from right to left: least significant digit comes last.
516   // Maybe because we use Arabic numbers, and Arabs write RTL?
517   if (is_hex) {
518     for (n = 0; v; v >>= 4) buf[s + n++] = letters[v & 15];
519   } else {
520     for (n = 0; v; v /= 10) buf[s + n++] = letters[v % 10];
521   }
522   // Reverse a string
523   for (i = 0; i < n / 2; i++) {
524     char t = buf[s + i];
525     buf[s + i] = buf[s + n - i - 1], buf[s + n - i - 1] = t;
526   }
527   if (val == 0) buf[n++] = '0';  // Handle special case
528   return n + s;
529 }
530
531 static size_t scpy(void (*out)(char, void *), void *ptr, char *buf,
532                           size_t len) {
533   size_t i = 0;
534   while (i < len && buf[i] != '\0') out(buf[i++], ptr);
535   return i;
536 }
537
538 size_t mg_xprintf(void (*out)(char, void *), void *ptr, const char *fmt, ...) {
539   size_t len = 0;
540   va_list ap;
541   va_start(ap, fmt);
542   len = mg_vxprintf(out, ptr, fmt, &ap);
543   va_end(ap);
544   return len;
545 }
546
547 size_t mg_vxprintf(void (*out)(char, void *), void *param, const char *fmt,
548                    va_list *ap) {
549   size_t i = 0, n = 0;
550   while (fmt[i] != '\0') {
551     if (fmt[i] == '%') {
552       size_t j, k, x = 0, is_long = 0, w = 0 /* width */, pr = ~0U /* prec */;
553       char pad = ' ', minus = 0, c = fmt[++i];
554       if (c == '#') x++, c = fmt[++i];
555       if (c == '-') minus++, c = fmt[++i];
556       if (c == '0') pad = '0', c = fmt[++i];
557       while (is_digit(c)) w *= 10, w += (size_t) (c - '0'), c = fmt[++i];
558       if (c == '.') {
559         c = fmt[++i];
560         if (c == '*') {
561           pr = (size_t) va_arg(*ap, int);
562           c = fmt[++i];
563         } else {
564           pr = 0;
565           while (is_digit(c)) pr *= 10, pr += (size_t) (c - '0'), c = fmt[++i];
566         }
567       }
568       while (c == 'h') c = fmt[++i];  // Treat h and hh as int
569       if (c == 'l') {
570         is_long++, c = fmt[++i];
571         if (c == 'l') is_long++, c = fmt[++i];
572       }
573       if (c == 'p') x = 1, is_long = 1;
574       if (c == 'd' || c == 'u' || c == 'x' || c == 'X' || c == 'p' ||
575           c == 'g' || c == 'f') {
576         bool s = (c == 'd'), h = (c == 'x' || c == 'X' || c == 'p');
577         char tmp[40];
578         size_t xl = x ? 2 : 0;
579         if (c == 'g' || c == 'f') {
580           double v = va_arg(*ap, double);
581           if (pr == ~0U) pr = 6;
582           k = mg_dtoa(tmp, sizeof(tmp), v, (int) pr, c == 'g');
583         } else if (is_long == 2) {
584           int64_t v = va_arg(*ap, int64_t);
585           k = mg_lld(tmp, v, s, h);
586         } else if (is_long == 1) {
587           long v = va_arg(*ap, long);
588           k = mg_lld(tmp, s ? (int64_t) v : (int64_t) (unsigned long) v, s, h);
589         } else {
590           int v = va_arg(*ap, int);
591           k = mg_lld(tmp, s ? (int64_t) v : (int64_t) (unsigned) v, s, h);
592         }
593         for (j = 0; j < xl && w > 0; j++) w--;
594         for (j = 0; pad == ' ' && !minus && k < w && j + k < w; j++)
595           n += scpy(out, param, &pad, 1);
596         n += scpy(out, param, (char *) "0x", xl);
597         for (j = 0; pad == '0' && k < w && j + k < w; j++)
598           n += scpy(out, param, &pad, 1);
599         n += scpy(out, param, tmp, k);
600         for (j = 0; pad == ' ' && minus && k < w && j + k < w; j++)
601           n += scpy(out, param, &pad, 1);
602       } else if (c == 'm' || c == 'M') {
603         mg_pm_t f = va_arg(*ap, mg_pm_t);
604         if (c == 'm') out('"', param);
605         n += f(out, param, ap);
606         if (c == 'm') n += 2, out('"', param);
607       } else if (c == 'c') {
608         int ch = va_arg(*ap, int);
609         out((char) ch, param);
610         n++;
611       } else if (c == 's') {
612         char *p = va_arg(*ap, char *);
613         if (pr == ~0U) pr = p == NULL ? 0 : strlen(p);
614         for (j = 0; !minus && pr < w && j + pr < w; j++)
615           n += scpy(out, param, &pad, 1);
616         n += scpy(out, param, p, pr);
617         for (j = 0; minus && pr < w && j + pr < w; j++)
618           n += scpy(out, param, &pad, 1);
619       } else if (c == '%') {
620         out('%', param);
621         n++;
622       } else {
623         out('%', param);
624         out(c, param);
625         n += 2;
626       }
627       i++;
628     } else {
629       out(fmt[i], param), n++, i++;
630     }
631   }
632   return n;
633 }
634
635 #ifdef MG_ENABLE_LINES
636 #line 1 "src/fs.c"
637 #endif
638
639
640
641 struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags) {
642   struct mg_fd *fd = (struct mg_fd *) calloc(1, sizeof(*fd));
643   if (fd != NULL) {
644     fd->fd = fs->op(path, flags);
645     fd->fs = fs;
646     if (fd->fd == NULL) {
647       free(fd);
648       fd = NULL;
649     }
650   }
651   return fd;
652 }
653
654 void mg_fs_close(struct mg_fd *fd) {
655   if (fd != NULL) {
656     fd->fs->cl(fd->fd);
657     free(fd);
658   }
659 }
660
661 char *mg_file_read(struct mg_fs *fs, const char *path, size_t *sizep) {
662   struct mg_fd *fd;
663   char *data = NULL;
664   size_t size = 0;
665   fs->st(path, &size, NULL);
666   if ((fd = mg_fs_open(fs, path, MG_FS_READ)) != NULL) {
667     data = (char *) calloc(1, size + 1);
668     if (data != NULL) {
669       if (fs->rd(fd->fd, data, size) != size) {
670         free(data);
671         data = NULL;
672       } else {
673         data[size] = '\0';
674         if (sizep != NULL) *sizep = size;
675       }
676     }
677     mg_fs_close(fd);
678   }
679   return data;
680 }
681
682 bool mg_file_write(struct mg_fs *fs, const char *path, const void *buf,
683                    size_t len) {
684   bool result = false;
685   struct mg_fd *fd;
686   char tmp[MG_PATH_MAX];
687   mg_snprintf(tmp, sizeof(tmp), "%s..%d", path, rand());
688   if ((fd = mg_fs_open(fs, tmp, MG_FS_WRITE)) != NULL) {
689     result = fs->wr(fd->fd, buf, len) == len;
690     mg_fs_close(fd);
691     if (result) {
692       fs->rm(path);
693       fs->mv(tmp, path);
694     } else {
695       fs->rm(tmp);
696     }
697   }
698   return result;
699 }
700
701 bool mg_file_printf(struct mg_fs *fs, const char *path, const char *fmt, ...) {
702   va_list ap;
703   char *data;
704   bool result = false;
705   va_start(ap, fmt);
706   data = mg_vmprintf(fmt, &ap);
707   va_end(ap);
708   result = mg_file_write(fs, path, data, strlen(data));
709   free(data);
710   return result;
711 }
712
713 #ifdef MG_ENABLE_LINES
714 #line 1 "src/fs_fat.c"
715 #endif
716
717
718
719 #if MG_ENABLE_FATFS
720 #include <ff.h>
721
722 static int mg_days_from_epoch(int y, int m, int d) {
723   y -= m <= 2;
724   int era = y / 400;
725   int yoe = y - era * 400;
726   int doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;
727   int doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
728   return era * 146097 + doe - 719468;
729 }
730
731 static time_t mg_timegm(const struct tm *t) {
732   int year = t->tm_year + 1900;
733   int month = t->tm_mon;  // 0-11
734   if (month > 11) {
735     year += month / 12;
736     month %= 12;
737   } else if (month < 0) {
738     int years_diff = (11 - month) / 12;
739     year -= years_diff;
740     month += 12 * years_diff;
741   }
742   int x = mg_days_from_epoch(year, month + 1, t->tm_mday);
743   return 60 * (60 * (24L * x + t->tm_hour) + t->tm_min) + t->tm_sec;
744 }
745
746 static time_t ff_time_to_epoch(uint16_t fdate, uint16_t ftime) {
747   struct tm tm;
748   memset(&tm, 0, sizeof(struct tm));
749   tm.tm_sec = (ftime << 1) & 0x3e;
750   tm.tm_min = ((ftime >> 5) & 0x3f);
751   tm.tm_hour = ((ftime >> 11) & 0x1f);
752   tm.tm_mday = (fdate & 0x1f);
753   tm.tm_mon = ((fdate >> 5) & 0x0f) - 1;
754   tm.tm_year = ((fdate >> 9) & 0x7f) + 80;
755   return mg_timegm(&tm);
756 }
757
758 static int ff_stat(const char *path, size_t *size, time_t *mtime) {
759   FILINFO fi;
760   if (path[0] == '\0') {
761     if (size) *size = 0;
762     if (mtime) *mtime = 0;
763     return MG_FS_DIR;
764   } else if (f_stat(path, &fi) == 0) {
765     if (size) *size = (size_t) fi.fsize;
766     if (mtime) *mtime = ff_time_to_epoch(fi.fdate, fi.ftime);
767     return MG_FS_READ | MG_FS_WRITE | ((fi.fattrib & AM_DIR) ? MG_FS_DIR : 0);
768   } else {
769     return 0;
770   }
771 }
772
773 static void ff_list(const char *dir, void (*fn)(const char *, void *),
774                     void *userdata) {
775   DIR d;
776   FILINFO fi;
777   if (f_opendir(&d, dir) == FR_OK) {
778     while (f_readdir(&d, &fi) == FR_OK && fi.fname[0] != '\0') {
779       if (!strcmp(fi.fname, ".") || !strcmp(fi.fname, "..")) continue;
780       fn(fi.fname, userdata);
781     }
782     f_closedir(&d);
783   }
784 }
785
786 static void *ff_open(const char *path, int flags) {
787   FIL f;
788   unsigned char mode = FA_READ;
789   if (flags & MG_FS_WRITE) mode |= FA_WRITE | FA_OPEN_ALWAYS | FA_OPEN_APPEND;
790   if (f_open(&f, path, mode) == 0) {
791     FIL *fp;
792     if ((fp = calloc(1, sizeof(*fp))) != NULL) {
793       memcpy(fp, &f, sizeof(*fp));
794       return fp;
795     }
796   }
797   return NULL;
798 }
799
800 static void ff_close(void *fp) {
801   if (fp != NULL) {
802     f_close((FIL *) fp);
803     free(fp);
804   }
805 }
806
807 static size_t ff_read(void *fp, void *buf, size_t len) {
808   UINT n = 0, misalign = ((size_t) buf) & 3;
809   if (misalign) {
810     char aligned[4];
811     f_read((FIL *) fp, aligned, len > misalign ? misalign : len, &n);
812     memcpy(buf, aligned, n);
813   } else {
814     f_read((FIL *) fp, buf, len, &n);
815   }
816   return n;
817 }
818
819 static size_t ff_write(void *fp, const void *buf, size_t len) {
820   UINT n = 0;
821   return f_write((FIL *) fp, (char *) buf, len, &n) == FR_OK ? n : 0;
822 }
823
824 static size_t ff_seek(void *fp, size_t offset) {
825   f_lseek((FIL *) fp, offset);
826   return offset;
827 }
828
829 static bool ff_rename(const char *from, const char *to) {
830   return f_rename(from, to) == FR_OK;
831 }
832
833 static bool ff_remove(const char *path) {
834   return f_unlink(path) == FR_OK;
835 }
836
837 static bool ff_mkdir(const char *path) {
838   return f_mkdir(path) == FR_OK;
839 }
840
841 struct mg_fs mg_fs_fat = {ff_stat,  ff_list, ff_open,   ff_close,  ff_read,
842                           ff_write, ff_seek, ff_rename, ff_remove, ff_mkdir};
843 #endif
844
845 #ifdef MG_ENABLE_LINES
846 #line 1 "src/fs_packed.c"
847 #endif
848
849
850
851
852 struct packed_file {
853   const char *data;
854   size_t size;
855   size_t pos;
856 };
857
858 const char *mg_unpack(const char *path, size_t *size, time_t *mtime);
859 const char *mg_unlist(size_t no);
860
861 #if MG_ENABLE_PACKED_FS
862 #else
863 const char *mg_unpack(const char *path, size_t *size, time_t *mtime) {
864   (void) path, (void) size, (void) mtime;
865   return NULL;
866 }
867 const char *mg_unlist(size_t no) {
868   (void) no;
869   return NULL;
870 }
871 #endif
872
873 static int is_dir_prefix(const char *prefix, size_t n, const char *path) {
874   // MG_INFO(("[%.*s] [%s] %c", (int) n, prefix, path, path[n]));
875   return n < strlen(path) && strncmp(prefix, path, n) == 0 &&
876          (n == 0 || path[n] == '/' || path[n - 1] == '/');
877 }
878
879 static int packed_stat(const char *path, size_t *size, time_t *mtime) {
880   const char *p;
881   size_t i, n = strlen(path);
882   if (mg_unpack(path, size, mtime)) return MG_FS_READ;  // Regular file
883   // Scan all files. If `path` is a dir prefix for any of them, it's a dir
884   for (i = 0; (p = mg_unlist(i)) != NULL; i++) {
885     if (is_dir_prefix(path, n, p)) return MG_FS_DIR;
886   }
887   return 0;
888 }
889
890 static void packed_list(const char *dir, void (*fn)(const char *, void *),
891                         void *userdata) {
892   char buf[MG_PATH_MAX], tmp[sizeof(buf)];
893   const char *path, *begin, *end;
894   size_t i, n = strlen(dir);
895   tmp[0] = '\0';  // Previously listed entry
896   for (i = 0; (path = mg_unlist(i)) != NULL; i++) {
897     if (!is_dir_prefix(dir, n, path)) continue;
898     begin = &path[n + 1];
899     end = strchr(begin, '/');
900     if (end == NULL) end = begin + strlen(begin);
901     mg_snprintf(buf, sizeof(buf), "%.*s", (int) (end - begin), begin);
902     buf[sizeof(buf) - 1] = '\0';
903     // If this entry has been already listed, skip
904     // NOTE: we're assuming that file list is sorted alphabetically
905     if (strcmp(buf, tmp) == 0) continue;
906     fn(buf, userdata);  // Not yet listed, call user function
907     strcpy(tmp, buf);   // And save this entry as listed
908   }
909 }
910
911 static void *packed_open(const char *path, int flags) {
912   size_t size = 0;
913   const char *data = mg_unpack(path, &size, NULL);
914   struct packed_file *fp = NULL;
915   if (data == NULL) return NULL;
916   if (flags & MG_FS_WRITE) return NULL;
917   if ((fp = (struct packed_file *) calloc(1, sizeof(*fp))) != NULL) {
918     fp->size = size;
919     fp->data = data;
920   }
921   return (void *) fp;
922 }
923
924 static void packed_close(void *fp) {
925   if (fp != NULL) free(fp);
926 }
927
928 static size_t packed_read(void *fd, void *buf, size_t len) {
929   struct packed_file *fp = (struct packed_file *) fd;
930   if (fp->pos + len > fp->size) len = fp->size - fp->pos;
931   memcpy(buf, &fp->data[fp->pos], len);
932   fp->pos += len;
933   return len;
934 }
935
936 static size_t packed_write(void *fd, const void *buf, size_t len) {
937   (void) fd, (void) buf, (void) len;
938   return 0;
939 }
940
941 static size_t packed_seek(void *fd, size_t offset) {
942   struct packed_file *fp = (struct packed_file *) fd;
943   fp->pos = offset;
944   if (fp->pos > fp->size) fp->pos = fp->size;
945   return fp->pos;
946 }
947
948 static bool packed_rename(const char *from, const char *to) {
949   (void) from, (void) to;
950   return false;
951 }
952
953 static bool packed_remove(const char *path) {
954   (void) path;
955   return false;
956 }
957
958 static bool packed_mkdir(const char *path) {
959   (void) path;
960   return false;
961 }
962
963 struct mg_fs mg_fs_packed = {
964     packed_stat,  packed_list, packed_open,   packed_close,  packed_read,
965     packed_write, packed_seek, packed_rename, packed_remove, packed_mkdir};
966
967 #ifdef MG_ENABLE_LINES
968 #line 1 "src/fs_posix.c"
969 #endif
970
971
972 #if MG_ENABLE_FILE
973
974 #ifndef MG_STAT_STRUCT
975 #define MG_STAT_STRUCT stat
976 #endif
977
978 #ifndef MG_STAT_FUNC
979 #define MG_STAT_FUNC stat
980 #endif
981
982 static int p_stat(const char *path, size_t *size, time_t *mtime) {
983 #if !defined(S_ISDIR)
984   MG_ERROR(("stat() API is not supported. %p %p %p", path, size, mtime));
985   return 0;
986 #else
987 #if MG_ARCH == MG_ARCH_WIN32
988   struct _stati64 st;
989   wchar_t tmp[MG_PATH_MAX];
990   MultiByteToWideChar(CP_UTF8, 0, path, -1, tmp, sizeof(tmp) / sizeof(tmp[0]));
991   if (_wstati64(tmp, &st) != 0) return 0;
992   // If path is a symlink, windows reports 0 in st.st_size.
993   // Get a real file size by opening it and jumping to the end
994   if (st.st_size == 0 && (st.st_mode & _S_IFREG)) {
995     FILE *fp = _wfopen(tmp, L"rb");
996     if (fp != NULL) {
997       fseek(fp, 0, SEEK_END);
998       if (ftell(fp) > 0) st.st_size = ftell(fp); // Use _ftelli64 on win10+
999       fclose(fp);
1000     }
1001   }
1002 #else
1003   struct MG_STAT_STRUCT st;
1004   if (MG_STAT_FUNC(path, &st) != 0) return 0;
1005 #endif
1006   if (size) *size = (size_t) st.st_size;
1007   if (mtime) *mtime = st.st_mtime;
1008   return MG_FS_READ | MG_FS_WRITE | (S_ISDIR(st.st_mode) ? MG_FS_DIR : 0);
1009 #endif
1010 }
1011
1012 #if MG_ARCH == MG_ARCH_WIN32
1013 struct dirent {
1014   char d_name[MAX_PATH];
1015 };
1016
1017 typedef struct win32_dir {
1018   HANDLE handle;
1019   WIN32_FIND_DATAW info;
1020   struct dirent result;
1021 } DIR;
1022
1023 int gettimeofday(struct timeval *tv, void *tz) {
1024   FILETIME ft;
1025   unsigned __int64 tmpres = 0;
1026
1027   if (tv != NULL) {
1028     GetSystemTimeAsFileTime(&ft);
1029     tmpres |= ft.dwHighDateTime;
1030     tmpres <<= 32;
1031     tmpres |= ft.dwLowDateTime;
1032     tmpres /= 10;  // convert into microseconds
1033     tmpres -= (int64_t) 11644473600000000;
1034     tv->tv_sec = (long) (tmpres / 1000000UL);
1035     tv->tv_usec = (long) (tmpres % 1000000UL);
1036   }
1037   (void) tz;
1038   return 0;
1039 }
1040
1041 static int to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len) {
1042   int ret;
1043   char buf[MAX_PATH * 2], buf2[MAX_PATH * 2], *p;
1044   strncpy(buf, path, sizeof(buf));
1045   buf[sizeof(buf) - 1] = '\0';
1046   // Trim trailing slashes. Leave backslash for paths like "X:\"
1047   p = buf + strlen(buf) - 1;
1048   while (p > buf && p[-1] != ':' && (p[0] == '\\' || p[0] == '/')) *p-- = '\0';
1049   memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
1050   ret = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len);
1051   // Convert back to Unicode. If doubly-converted string does not match the
1052   // original, something is fishy, reject.
1053   WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2),
1054                       NULL, NULL);
1055   if (strcmp(buf, buf2) != 0) {
1056     wbuf[0] = L'\0';
1057     ret = 0;
1058   }
1059   return ret;
1060 }
1061
1062 DIR *opendir(const char *name) {
1063   DIR *d = NULL;
1064   wchar_t wpath[MAX_PATH];
1065   DWORD attrs;
1066
1067   if (name == NULL) {
1068     SetLastError(ERROR_BAD_ARGUMENTS);
1069   } else if ((d = (DIR *) calloc(1, sizeof(*d))) == NULL) {
1070     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1071   } else {
1072     to_wchar(name, wpath, sizeof(wpath) / sizeof(wpath[0]));
1073     attrs = GetFileAttributesW(wpath);
1074     if (attrs != 0Xffffffff && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
1075       (void) wcscat(wpath, L"\\*");
1076       d->handle = FindFirstFileW(wpath, &d->info);
1077       d->result.d_name[0] = '\0';
1078     } else {
1079       free(d);
1080       d = NULL;
1081     }
1082   }
1083   return d;
1084 }
1085
1086 int closedir(DIR *d) {
1087   int result = 0;
1088   if (d != NULL) {
1089     if (d->handle != INVALID_HANDLE_VALUE)
1090       result = FindClose(d->handle) ? 0 : -1;
1091     free(d);
1092   } else {
1093     result = -1;
1094     SetLastError(ERROR_BAD_ARGUMENTS);
1095   }
1096   return result;
1097 }
1098
1099 struct dirent *readdir(DIR *d) {
1100   struct dirent *result = NULL;
1101   if (d != NULL) {
1102     memset(&d->result, 0, sizeof(d->result));
1103     if (d->handle != INVALID_HANDLE_VALUE) {
1104       result = &d->result;
1105       WideCharToMultiByte(CP_UTF8, 0, d->info.cFileName, -1, result->d_name,
1106                           sizeof(result->d_name), NULL, NULL);
1107       if (!FindNextFileW(d->handle, &d->info)) {
1108         FindClose(d->handle);
1109         d->handle = INVALID_HANDLE_VALUE;
1110       }
1111     } else {
1112       SetLastError(ERROR_FILE_NOT_FOUND);
1113     }
1114   } else {
1115     SetLastError(ERROR_BAD_ARGUMENTS);
1116   }
1117   return result;
1118 }
1119 #endif
1120
1121 static void p_list(const char *dir, void (*fn)(const char *, void *),
1122                    void *userdata) {
1123 #if MG_ENABLE_DIRLIST
1124   struct dirent *dp;
1125   DIR *dirp;
1126   if ((dirp = (opendir(dir))) == NULL) return;
1127   while ((dp = readdir(dirp)) != NULL) {
1128     if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue;
1129     fn(dp->d_name, userdata);
1130   }
1131   closedir(dirp);
1132 #else
1133   (void) dir, (void) fn, (void) userdata;
1134 #endif
1135 }
1136
1137 static void *p_open(const char *path, int flags) {
1138   const char *mode = flags == MG_FS_READ ? "rb" : "a+b";
1139 #if MG_ARCH == MG_ARCH_WIN32
1140   wchar_t b1[MG_PATH_MAX], b2[10];
1141   MultiByteToWideChar(CP_UTF8, 0, path, -1, b1, sizeof(b1) / sizeof(b1[0]));
1142   MultiByteToWideChar(CP_UTF8, 0, mode, -1, b2, sizeof(b2) / sizeof(b2[0]));
1143   return (void *) _wfopen(b1, b2);
1144 #else
1145   return (void *) fopen(path, mode);
1146 #endif
1147 }
1148
1149 static void p_close(void *fp) {
1150   fclose((FILE *) fp);
1151 }
1152
1153 static size_t p_read(void *fp, void *buf, size_t len) {
1154   return fread(buf, 1, len, (FILE *) fp);
1155 }
1156
1157 static size_t p_write(void *fp, const void *buf, size_t len) {
1158   return fwrite(buf, 1, len, (FILE *) fp);
1159 }
1160
1161 static size_t p_seek(void *fp, size_t offset) {
1162 #if (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64) ||  \
1163     (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \
1164     (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
1165   if (fseeko((FILE *) fp, (off_t) offset, SEEK_SET) != 0) (void) 0;
1166 #else
1167   if (fseek((FILE *) fp, (long) offset, SEEK_SET) != 0) (void) 0;
1168 #endif
1169   return (size_t) ftell((FILE *) fp);
1170 }
1171
1172 static bool p_rename(const char *from, const char *to) {
1173   return rename(from, to) == 0;
1174 }
1175
1176 static bool p_remove(const char *path) {
1177   return remove(path) == 0;
1178 }
1179
1180 static bool p_mkdir(const char *path) {
1181   return mkdir(path, 0775) == 0;
1182 }
1183
1184 #else
1185
1186 static int p_stat(const char *path, size_t *size, time_t *mtime) {
1187   (void) path, (void) size, (void) mtime;
1188   return 0;
1189 }
1190 static void p_list(const char *path, void (*fn)(const char *, void *),
1191                    void *userdata) {
1192   (void) path, (void) fn, (void) userdata;
1193 }
1194 static void *p_open(const char *path, int flags) {
1195   (void) path, (void) flags;
1196   return NULL;
1197 }
1198 static void p_close(void *fp) {
1199   (void) fp;
1200 }
1201 static size_t p_read(void *fd, void *buf, size_t len) {
1202   (void) fd, (void) buf, (void) len;
1203   return 0;
1204 }
1205 static size_t p_write(void *fd, const void *buf, size_t len) {
1206   (void) fd, (void) buf, (void) len;
1207   return 0;
1208 }
1209 static size_t p_seek(void *fd, size_t offset) {
1210   (void) fd, (void) offset;
1211   return (size_t) ~0;
1212 }
1213 static bool p_rename(const char *from, const char *to) {
1214   (void) from, (void) to;
1215   return false;
1216 }
1217 static bool p_remove(const char *path) {
1218   (void) path;
1219   return false;
1220 }
1221 static bool p_mkdir(const char *path) {
1222   (void) path;
1223   return false;
1224 }
1225 #endif
1226
1227 struct mg_fs mg_fs_posix = {p_stat,  p_list, p_open,   p_close,  p_read,
1228                             p_write, p_seek, p_rename, p_remove, p_mkdir};
1229
1230 #ifdef MG_ENABLE_LINES
1231 #line 1 "src/http.c"
1232 #endif
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246 bool mg_to_size_t(struct mg_str str, size_t *val);
1247 bool mg_to_size_t(struct mg_str str, size_t *val) {
1248   uint64_t result = 0, max = 1844674407370955160 /* (UINT64_MAX-9)/10 */;
1249   size_t i = 0;
1250   while (i < str.len && (str.ptr[i] == ' ' || str.ptr[i] == '\t')) i++;
1251   if (i < str.len && str.ptr[i] == '-') return false;
1252   while (i < str.len && str.ptr[i] >= '0' && str.ptr[i] <= '9') {
1253     if (result > max) return false;
1254     result *= 10;
1255     result += (unsigned) (str.ptr[i] - '0');
1256     i++;
1257   }
1258   *val = (size_t) result;
1259   return true;
1260 }
1261
1262 // Chunk deletion marker is the MSB in the "processed" counter
1263 #define MG_DMARK ((size_t) 1 << (sizeof(size_t) * 8 - 1))
1264
1265 // Multipart POST example:
1266 // --xyz
1267 // Content-Disposition: form-data; name="val"
1268 //
1269 // abcdef
1270 // --xyz
1271 // Content-Disposition: form-data; name="foo"; filename="a.txt"
1272 // Content-Type: text/plain
1273 //
1274 // hello world
1275 //
1276 // --xyz--
1277 size_t mg_http_next_multipart(struct mg_str body, size_t ofs,
1278                               struct mg_http_part *part) {
1279   struct mg_str cd = mg_str_n("Content-Disposition", 19);
1280   const char *s = body.ptr;
1281   size_t b = ofs, h1, h2, b1, b2, max = body.len;
1282
1283   // Init part params
1284   if (part != NULL) part->name = part->filename = part->body = mg_str_n(0, 0);
1285
1286   // Skip boundary
1287   while (b + 2 < max && s[b] != '\r' && s[b + 1] != '\n') b++;
1288   if (b <= ofs || b + 2 >= max) return 0;
1289   // MG_INFO(("B: %zu %zu [%.*s]", ofs, b - ofs, (int) (b - ofs), s));
1290
1291   // Skip headers
1292   h1 = h2 = b + 2;
1293   for (;;) {
1294     while (h2 + 2 < max && s[h2] != '\r' && s[h2 + 1] != '\n') h2++;
1295     if (h2 == h1) break;
1296     if (h2 + 2 >= max) return 0;
1297     // MG_INFO(("Header: [%.*s]", (int) (h2 - h1), &s[h1]));
1298     if (part != NULL && h1 + cd.len + 2 < h2 && s[h1 + cd.len] == ':' &&
1299         mg_ncasecmp(&s[h1], cd.ptr, cd.len) == 0) {
1300       struct mg_str v = mg_str_n(&s[h1 + cd.len + 2], h2 - (h1 + cd.len + 2));
1301       part->name = mg_http_get_header_var(v, mg_str_n("name", 4));
1302       part->filename = mg_http_get_header_var(v, mg_str_n("filename", 8));
1303     }
1304     h1 = h2 = h2 + 2;
1305   }
1306   b1 = b2 = h2 + 2;
1307   while (b2 + 2 + (b - ofs) + 2 < max && !(s[b2] == '\r' && s[b2 + 1] == '\n' &&
1308                                            memcmp(&s[b2 + 2], s, b - ofs) == 0))
1309     b2++;
1310
1311   if (b2 + 2 >= max) return 0;
1312   if (part != NULL) part->body = mg_str_n(&s[b1], b2 - b1);
1313   // MG_INFO(("Body: [%.*s]", (int) (b2 - b1), &s[b1]));
1314   return b2 + 2;
1315 }
1316
1317 void mg_http_bauth(struct mg_connection *c, const char *user,
1318                    const char *pass) {
1319   struct mg_str u = mg_str(user), p = mg_str(pass);
1320   size_t need = c->send.len + 36 + (u.len + p.len) * 2;
1321   if (c->send.size < need) mg_iobuf_resize(&c->send, need);
1322   if (c->send.size >= need) {
1323     int i, n = 0;
1324     char *buf = (char *) &c->send.buf[c->send.len];
1325     memcpy(buf, "Authorization: Basic ", 21);  // DON'T use mg_send!
1326     for (i = 0; i < (int) u.len; i++) {
1327       n = mg_base64_update(((unsigned char *) u.ptr)[i], buf + 21, n);
1328     }
1329     if (p.len > 0) {
1330       n = mg_base64_update(':', buf + 21, n);
1331       for (i = 0; i < (int) p.len; i++) {
1332         n = mg_base64_update(((unsigned char *) p.ptr)[i], buf + 21, n);
1333       }
1334     }
1335     n = mg_base64_final(buf + 21, n);
1336     c->send.len += 21 + (size_t) n + 2;
1337     memcpy(&c->send.buf[c->send.len - 2], "\r\n", 2);
1338   } else {
1339     MG_ERROR(("%lu oom %d->%d ", c->id, (int) c->send.size, (int) need));
1340   }
1341 }
1342
1343 struct mg_str mg_http_var(struct mg_str buf, struct mg_str name) {
1344   struct mg_str k, v, result = mg_str_n(NULL, 0);
1345   while (mg_split(&buf, &k, &v, '&')) {
1346     if (name.len == k.len && mg_ncasecmp(name.ptr, k.ptr, k.len) == 0) {
1347       result = v;
1348       break;
1349     }
1350   }
1351   return result;
1352 }
1353
1354 int mg_http_get_var(const struct mg_str *buf, const char *name, char *dst,
1355                     size_t dst_len) {
1356   int len;
1357   if (dst == NULL || dst_len == 0) {
1358     len = -2;  // Bad destination
1359   } else if (buf->ptr == NULL || name == NULL || buf->len == 0) {
1360     len = -1;  // Bad source
1361     dst[0] = '\0';
1362   } else {
1363     struct mg_str v = mg_http_var(*buf, mg_str(name));
1364     if (v.ptr == NULL) {
1365       len = -4;  // Name does not exist
1366     } else {
1367       len = mg_url_decode(v.ptr, v.len, dst, dst_len, 1);
1368       if (len < 0) len = -3;  // Failed to decode
1369     }
1370   }
1371   return len;
1372 }
1373
1374 static bool isx(int c) {
1375   return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
1376          (c >= 'A' && c <= 'F');
1377 }
1378
1379 int mg_url_decode(const char *src, size_t src_len, char *dst, size_t dst_len,
1380                   int is_form_url_encoded) {
1381   size_t i, j;
1382   for (i = j = 0; i < src_len && j + 1 < dst_len; i++, j++) {
1383     if (src[i] == '%') {
1384       // Use `i + 2 < src_len`, not `i < src_len - 2`, note small src_len
1385       if (i + 2 < src_len && isx(src[i + 1]) && isx(src[i + 2])) {
1386         mg_unhex(src + i + 1, 2, (uint8_t *) &dst[j]);
1387         i += 2;
1388       } else {
1389         return -1;
1390       }
1391     } else if (is_form_url_encoded && src[i] == '+') {
1392       dst[j] = ' ';
1393     } else {
1394       dst[j] = src[i];
1395     }
1396   }
1397   if (j < dst_len) dst[j] = '\0';  // Null-terminate the destination
1398   return i >= src_len && j < dst_len ? (int) j : -1;
1399 }
1400
1401 static bool isok(uint8_t c) {
1402   return c == '\n' || c == '\r' || c >= ' ';
1403 }
1404
1405 int mg_http_get_request_len(const unsigned char *buf, size_t buf_len) {
1406   size_t i;
1407   for (i = 0; i < buf_len; i++) {
1408     if (!isok(buf[i])) return -1;
1409     if ((i > 0 && buf[i] == '\n' && buf[i - 1] == '\n') ||
1410         (i > 3 && buf[i] == '\n' && buf[i - 1] == '\r' && buf[i - 2] == '\n'))
1411       return (int) i + 1;
1412   }
1413   return 0;
1414 }
1415
1416 static const char *skip(const char *s, const char *e, const char *d,
1417                         struct mg_str *v) {
1418   v->ptr = s;
1419   while (s < e && *s != '\n' && strchr(d, *s) == NULL) s++;
1420   v->len = (size_t) (s - v->ptr);
1421   while (s < e && strchr(d, *s) != NULL) s++;
1422   return s;
1423 }
1424
1425 struct mg_str *mg_http_get_header(struct mg_http_message *h, const char *name) {
1426   size_t i, n = strlen(name), max = sizeof(h->headers) / sizeof(h->headers[0]);
1427   for (i = 0; i < max && h->headers[i].name.len > 0; i++) {
1428     struct mg_str *k = &h->headers[i].name, *v = &h->headers[i].value;
1429     if (n == k->len && mg_ncasecmp(k->ptr, name, n) == 0) return v;
1430   }
1431   return NULL;
1432 }
1433
1434 static void mg_http_parse_headers(const char *s, const char *end,
1435                                   struct mg_http_header *h, int max_headers) {
1436   int i;
1437   for (i = 0; i < max_headers; i++) {
1438     struct mg_str k, v, tmp;
1439     const char *he = skip(s, end, "\n", &tmp);
1440     s = skip(s, he, ": \r\n", &k);
1441     s = skip(s, he, "\r\n", &v);
1442     if (k.len == tmp.len) continue;
1443     while (v.len > 0 && v.ptr[v.len - 1] == ' ') v.len--;  // Trim spaces
1444     if (k.len == 0) break;
1445     // MG_INFO(("--HH [%.*s] [%.*s] [%.*s]", (int) tmp.len - 1, tmp.ptr,
1446     //(int) k.len, k.ptr, (int) v.len, v.ptr));
1447     h[i].name = k;
1448     h[i].value = v;
1449   }
1450 }
1451
1452 int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
1453   int is_response, req_len = mg_http_get_request_len((unsigned char *) s, len);
1454   const char *end = s == NULL ? NULL : s + req_len, *qs;  // Cannot add to NULL
1455   struct mg_str *cl;
1456
1457   memset(hm, 0, sizeof(*hm));
1458   if (req_len <= 0) return req_len;
1459
1460   hm->message.ptr = hm->head.ptr = s;
1461   hm->body.ptr = end;
1462   hm->head.len = (size_t) req_len;
1463   hm->chunk.ptr = end;
1464   hm->message.len = hm->body.len = (size_t) ~0;  // Set body length to infinite
1465
1466   // Parse request line
1467   s = skip(s, end, " ", &hm->method);
1468   s = skip(s, end, " ", &hm->uri);
1469   s = skip(s, end, "\r\n", &hm->proto);
1470
1471   // Sanity check. Allow protocol/reason to be empty
1472   if (hm->method.len == 0 || hm->uri.len == 0) return -1;
1473
1474   // If URI contains '?' character, setup query string
1475   if ((qs = (const char *) memchr(hm->uri.ptr, '?', hm->uri.len)) != NULL) {
1476     hm->query.ptr = qs + 1;
1477     hm->query.len = (size_t) (&hm->uri.ptr[hm->uri.len] - (qs + 1));
1478     hm->uri.len = (size_t) (qs - hm->uri.ptr);
1479   }
1480
1481   mg_http_parse_headers(s, end, hm->headers,
1482                         sizeof(hm->headers) / sizeof(hm->headers[0]));
1483   if ((cl = mg_http_get_header(hm, "Content-Length")) != NULL) {
1484     if (mg_to_size_t(*cl, &hm->body.len) == false) return -1;
1485     hm->message.len = (size_t) req_len + hm->body.len;
1486   }
1487
1488   // mg_http_parse() is used to parse both HTTP requests and HTTP
1489   // responses. If HTTP response does not have Content-Length set, then
1490   // body is read until socket is closed, i.e. body.len is infinite (~0).
1491   //
1492   // For HTTP requests though, according to
1493   // http://tools.ietf.org/html/rfc7231#section-8.1.3,
1494   // only POST and PUT methods have defined body semantics.
1495   // Therefore, if Content-Length is not specified and methods are
1496   // not one of PUT or POST, set body length to 0.
1497   //
1498   // So, if it is HTTP request, and Content-Length is not set,
1499   // and method is not (PUT or POST) then reset body length to zero.
1500   is_response = mg_ncasecmp(hm->method.ptr, "HTTP/", 5) == 0;
1501   if (hm->body.len == (size_t) ~0 && !is_response &&
1502       mg_vcasecmp(&hm->method, "PUT") != 0 &&
1503       mg_vcasecmp(&hm->method, "POST") != 0) {
1504     hm->body.len = 0;
1505     hm->message.len = (size_t) req_len;
1506   }
1507
1508   // The 204 (No content) responses also have 0 body length
1509   if (hm->body.len == (size_t) ~0 && is_response &&
1510       mg_vcasecmp(&hm->uri, "204") == 0) {
1511     hm->body.len = 0;
1512     hm->message.len = (size_t) req_len;
1513   }
1514
1515   return req_len;
1516 }
1517
1518 static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt,
1519                                   va_list *ap) {
1520   size_t len = c->send.len;
1521   mg_send(c, "        \r\n", 10);
1522   mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
1523   if (c->send.len >= len + 10) {
1524     mg_snprintf((char *) c->send.buf + len, 9, "%08lx", c->send.len - len - 10);
1525     c->send.buf[len + 8] = '\r';
1526     if (c->send.len == len + 10) c->is_resp = 0;  // Last chunk, reset marker
1527   }
1528   mg_send(c, "\r\n", 2);
1529 }
1530
1531 void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...) {
1532   va_list ap;
1533   va_start(ap, fmt);
1534   mg_http_vprintf_chunk(c, fmt, &ap);
1535   va_end(ap);
1536 }
1537
1538 void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len) {
1539   mg_printf(c, "%lx\r\n", (unsigned long) len);
1540   mg_send(c, buf, len);
1541   mg_send(c, "\r\n", 2);
1542   if (len == 0) c->is_resp = 0;
1543 }
1544
1545 // clang-format off
1546 static const char *mg_http_status_code_str(int status_code) {
1547   switch (status_code) {
1548     case 100: return "Continue";
1549     case 201: return "Created";
1550     case 202: return "Accepted";
1551     case 204: return "No Content";
1552     case 206: return "Partial Content";
1553     case 301: return "Moved Permanently";
1554     case 302: return "Found";
1555     case 304: return "Not Modified";
1556     case 400: return "Bad Request";
1557     case 401: return "Unauthorized";
1558     case 403: return "Forbidden";
1559     case 404: return "Not Found";
1560     case 418: return "I'm a teapot";
1561     case 500: return "Internal Server Error";
1562     case 501: return "Not Implemented";
1563     default: return "OK";
1564   }
1565 }
1566 // clang-format on
1567
1568 void mg_http_reply(struct mg_connection *c, int code, const char *headers,
1569                    const char *fmt, ...) {
1570   va_list ap;
1571   size_t len;
1572   mg_printf(c, "HTTP/1.1 %d %s\r\n%sContent-Length:            \r\n\r\n", code,
1573             mg_http_status_code_str(code), headers == NULL ? "" : headers);
1574   len = c->send.len;
1575   va_start(ap, fmt);
1576   mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &ap);
1577   va_end(ap);
1578   if (c->send.len > 16) {
1579     size_t n = mg_snprintf((char *) &c->send.buf[len - 15], 11, "%-10lu",
1580                            (unsigned long) (c->send.len - len));
1581     c->send.buf[len - 15 + n] = ' ';  // Change ending 0 to space
1582   }
1583   c->is_resp = 0;
1584 }
1585
1586 static void http_cb(struct mg_connection *, int, void *, void *);
1587 static void restore_http_cb(struct mg_connection *c) {
1588   mg_fs_close((struct mg_fd *) c->pfn_data);
1589   c->pfn_data = NULL;
1590   c->pfn = http_cb;
1591   c->is_resp = 0;
1592 }
1593
1594 char *mg_http_etag(char *buf, size_t len, size_t size, time_t mtime);
1595 char *mg_http_etag(char *buf, size_t len, size_t size, time_t mtime) {
1596   mg_snprintf(buf, len, "\"%lld.%lld\"", (int64_t) mtime, (int64_t) size);
1597   return buf;
1598 }
1599
1600 static void static_cb(struct mg_connection *c, int ev, void *ev_data,
1601                       void *fn_data) {
1602   if (ev == MG_EV_WRITE || ev == MG_EV_POLL) {
1603     struct mg_fd *fd = (struct mg_fd *) fn_data;
1604     // Read to send IO buffer directly, avoid extra on-stack buffer
1605     size_t n, max = MG_IO_SIZE, space;
1606     size_t *cl = (size_t *) &c->data[(sizeof(c->data) - sizeof(size_t)) /
1607                                      sizeof(size_t) * sizeof(size_t)];
1608     if (c->send.size < max) mg_iobuf_resize(&c->send, max);
1609     if (c->send.len >= c->send.size) return;  // Rate limit
1610     if ((space = c->send.size - c->send.len) > *cl) space = *cl;
1611     n = fd->fs->rd(fd->fd, c->send.buf + c->send.len, space);
1612     c->send.len += n;
1613     *cl -= n;
1614     if (n == 0) restore_http_cb(c);
1615   } else if (ev == MG_EV_CLOSE) {
1616     restore_http_cb(c);
1617   }
1618   (void) ev_data;
1619 }
1620
1621 // Known mime types. Keep it outside guess_content_type() function, since
1622 // some environments don't like it defined there.
1623 // clang-format off
1624 static struct mg_str s_known_types[] = {
1625     MG_C_STR("html"), MG_C_STR("text/html; charset=utf-8"),
1626     MG_C_STR("htm"), MG_C_STR("text/html; charset=utf-8"),
1627     MG_C_STR("css"), MG_C_STR("text/css; charset=utf-8"),
1628     MG_C_STR("js"), MG_C_STR("text/javascript; charset=utf-8"),
1629     MG_C_STR("gif"), MG_C_STR("image/gif"),
1630     MG_C_STR("png"), MG_C_STR("image/png"),
1631     MG_C_STR("jpg"), MG_C_STR("image/jpeg"),
1632     MG_C_STR("jpeg"), MG_C_STR("image/jpeg"),
1633     MG_C_STR("woff"), MG_C_STR("font/woff"),
1634     MG_C_STR("ttf"), MG_C_STR("font/ttf"),
1635     MG_C_STR("svg"), MG_C_STR("image/svg+xml"),
1636     MG_C_STR("txt"), MG_C_STR("text/plain; charset=utf-8"),
1637     MG_C_STR("avi"), MG_C_STR("video/x-msvideo"),
1638     MG_C_STR("csv"), MG_C_STR("text/csv"),
1639     MG_C_STR("doc"), MG_C_STR("application/msword"),
1640     MG_C_STR("exe"), MG_C_STR("application/octet-stream"),
1641     MG_C_STR("gz"), MG_C_STR("application/gzip"),
1642     MG_C_STR("ico"), MG_C_STR("image/x-icon"),
1643     MG_C_STR("json"), MG_C_STR("application/json"),
1644     MG_C_STR("mov"), MG_C_STR("video/quicktime"),
1645     MG_C_STR("mp3"), MG_C_STR("audio/mpeg"),
1646     MG_C_STR("mp4"), MG_C_STR("video/mp4"),
1647     MG_C_STR("mpeg"), MG_C_STR("video/mpeg"),
1648     MG_C_STR("pdf"), MG_C_STR("application/pdf"),
1649     MG_C_STR("shtml"), MG_C_STR("text/html; charset=utf-8"),
1650     MG_C_STR("tgz"), MG_C_STR("application/tar-gz"),
1651     MG_C_STR("wav"), MG_C_STR("audio/wav"),
1652     MG_C_STR("webp"), MG_C_STR("image/webp"),
1653     MG_C_STR("zip"), MG_C_STR("application/zip"),
1654     MG_C_STR("3gp"), MG_C_STR("video/3gpp"),
1655     {0, 0},
1656 };
1657 // clang-format on
1658
1659 static struct mg_str guess_content_type(struct mg_str path, const char *extra) {
1660   struct mg_str k, v, s = mg_str(extra);
1661   size_t i = 0;
1662
1663   // Shrink path to its extension only
1664   while (i < path.len && path.ptr[path.len - i - 1] != '.') i++;
1665   path.ptr += path.len - i;
1666   path.len = i;
1667
1668   // Process user-provided mime type overrides, if any
1669   while (mg_commalist(&s, &k, &v)) {
1670     if (mg_strcmp(path, k) == 0) return v;
1671   }
1672
1673   // Process built-in mime types
1674   for (i = 0; s_known_types[i].ptr != NULL; i += 2) {
1675     if (mg_strcmp(path, s_known_types[i]) == 0) return s_known_types[i + 1];
1676   }
1677
1678   return mg_str("text/plain; charset=utf-8");
1679 }
1680
1681 static int getrange(struct mg_str *s, size_t *a, size_t *b) {
1682   size_t i, numparsed = 0;
1683   // MG_INFO(("%.*s", (int) s->len, s->ptr));
1684   for (i = 0; i + 6 < s->len; i++) {
1685     if (memcmp(&s->ptr[i], "bytes=", 6) == 0) {
1686       struct mg_str p = mg_str_n(s->ptr + i + 6, s->len - i - 6);
1687       if (p.len > 0 && p.ptr[0] >= '0' && p.ptr[0] <= '9') numparsed++;
1688       if (!mg_to_size_t(p, a)) return 0;
1689       // MG_INFO(("PPP [%.*s] %d", (int) p.len, p.ptr, numparsed));
1690       while (p.len && p.ptr[0] >= '0' && p.ptr[0] <= '9') p.ptr++, p.len--;
1691       if (p.len && p.ptr[0] == '-') p.ptr++, p.len--;
1692       if (!mg_to_size_t(p, b)) return 0;
1693       if (p.len > 0 && p.ptr[0] >= '0' && p.ptr[0] <= '9') numparsed++;
1694       // MG_INFO(("PPP [%.*s] %d", (int) p.len, p.ptr, numparsed));
1695       break;
1696     }
1697   }
1698   return (int) numparsed;
1699 }
1700
1701 void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
1702                         const char *path,
1703                         const struct mg_http_serve_opts *opts) {
1704   char etag[64], tmp[MG_PATH_MAX];
1705   struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
1706   struct mg_fd *fd = NULL;
1707   size_t size = 0;
1708   time_t mtime = 0;
1709   struct mg_str *inm = NULL;
1710   struct mg_str mime = guess_content_type(mg_str(path), opts->mime_types);
1711   bool gzip = false;
1712
1713   if (path != NULL) {
1714     // If a browser sends us "Accept-Encoding: gzip", try to open .gz first
1715     struct mg_str *ae = mg_http_get_header(hm, "Accept-Encoding");
1716     if (ae != NULL && mg_strstr(*ae, mg_str("gzip")) != NULL) {
1717       mg_snprintf(tmp, sizeof(tmp), "%s.gz", path);
1718       fd = mg_fs_open(fs, tmp, MG_FS_READ);
1719       if (fd != NULL) gzip = true, path = tmp;
1720     }
1721     // No luck opening .gz? Open what we've told to open
1722     if (fd == NULL) fd = mg_fs_open(fs, path, MG_FS_READ);
1723   }
1724
1725   // Failed to open, and page404 is configured? Open it, then
1726   if (fd == NULL && opts->page404 != NULL) {
1727     fd = mg_fs_open(fs, opts->page404, MG_FS_READ);
1728     mime = guess_content_type(mg_str(path), opts->mime_types);
1729     path = opts->page404;
1730   }
1731
1732   if (fd == NULL || fs->st(path, &size, &mtime) == 0) {
1733     mg_http_reply(c, 404, opts->extra_headers, "Not found\n");
1734     mg_fs_close(fd);
1735     // NOTE: mg_http_etag() call should go first!
1736   } else if (mg_http_etag(etag, sizeof(etag), size, mtime) != NULL &&
1737              (inm = mg_http_get_header(hm, "If-None-Match")) != NULL &&
1738              mg_vcasecmp(inm, etag) == 0) {
1739     mg_fs_close(fd);
1740     mg_http_reply(c, 304, opts->extra_headers, "");
1741   } else {
1742     int n, status = 200;
1743     char range[100];
1744     size_t r1 = 0, r2 = 0, cl = size;
1745     
1746     // Handle Range header
1747     struct mg_str *rh = mg_http_get_header(hm, "Range");
1748     range[0] = '\0';
1749     if (rh != NULL && (n = getrange(rh, &r1, &r2)) > 0) {
1750       // If range is specified like "400-", set second limit to content len
1751       if (n == 1) r2 = cl - 1;
1752       if (r1 > r2 || r2 >= cl) {
1753         status = 416;
1754         cl = 0;
1755         mg_snprintf(range, sizeof(range), "Content-Range: bytes */%lld\r\n",
1756                     (int64_t) size);
1757       } else {
1758         status = 206;
1759         cl = r2 - r1 + 1;
1760         mg_snprintf(range, sizeof(range),
1761                     "Content-Range: bytes %llu-%llu/%llu\r\n", (uint64_t) r1,
1762                     (uint64_t) (r1 + cl - 1), (uint64_t) size);
1763         fs->sk(fd->fd, r1);
1764       }
1765     }
1766     mg_printf(c,
1767               "HTTP/1.1 %d %s\r\n"
1768               "Content-Type: %.*s\r\n"
1769               "Etag: %s\r\n"
1770               "Content-Length: %llu\r\n"
1771               "%s%s%s\r\n",
1772               status, mg_http_status_code_str(status), (int) mime.len, mime.ptr,
1773               etag, (uint64_t) cl, gzip ? "Content-Encoding: gzip\r\n" : "",
1774               range, opts->extra_headers ? opts->extra_headers : "");
1775     if (mg_vcasecmp(&hm->method, "HEAD") == 0) {
1776       c->is_draining = 1;
1777       c->is_resp = 0;
1778       mg_fs_close(fd);
1779     } else {
1780       // Track to-be-sent content length at the end of c->data, aligned
1781       size_t *clp = (size_t *) &c->data[(sizeof(c->data) - sizeof(size_t)) /
1782                                         sizeof(size_t) * sizeof(size_t)];
1783       c->pfn = static_cb;
1784       c->pfn_data = fd;
1785       *clp = cl;
1786     }
1787   }
1788 }
1789
1790 struct printdirentrydata {
1791   struct mg_connection *c;
1792   struct mg_http_message *hm;
1793   const struct mg_http_serve_opts *opts;
1794   const char *dir;
1795 };
1796
1797 static void printdirentry(const char *name, void *userdata) {
1798   struct printdirentrydata *d = (struct printdirentrydata *) userdata;
1799   struct mg_fs *fs = d->opts->fs == NULL ? &mg_fs_posix : d->opts->fs;
1800   size_t size = 0;
1801   time_t t = 0;
1802   char path[MG_PATH_MAX], sz[40], mod[40];
1803   int flags, n = 0;
1804
1805   // MG_DEBUG(("[%s] [%s]", d->dir, name));
1806   if (mg_snprintf(path, sizeof(path), "%s%c%s", d->dir, '/', name) >
1807       sizeof(path)) {
1808     MG_ERROR(("%s truncated", name));
1809   } else if ((flags = fs->st(path, &size, &t)) == 0) {
1810     MG_ERROR(("%lu stat(%s): %d", d->c->id, path, errno));
1811   } else {
1812     const char *slash = flags & MG_FS_DIR ? "/" : "";
1813     if (flags & MG_FS_DIR) {
1814       mg_snprintf(sz, sizeof(sz), "%s", "[DIR]");
1815     } else {
1816       mg_snprintf(sz, sizeof(sz), "%lld", (uint64_t) size);
1817     }
1818 #if defined(MG_HTTP_DIRLIST_TIME_FMT)
1819     {
1820       char time_str[40];
1821       struct tm *time_info = localtime(&t);
1822       strftime(time_str, sizeof time_str, "%Y/%m/%d %H:%M:%S", time_info);
1823       mg_snprintf(mod, sizeof(mod), "%s", time_str);
1824     }
1825 #else
1826     mg_snprintf(mod, sizeof(mod), "%lu", (unsigned long) t);
1827 #endif
1828     n = (int) mg_url_encode(name, strlen(name), path, sizeof(path));
1829     mg_printf(d->c,
1830               "  <tr><td><a href=\"%.*s%s\">%s%s</a></td>"
1831               "<td name=%lu>%s</td><td name=%lld>%s</td></tr>\n",
1832               n, path, slash, name, slash, (unsigned long) t, mod,
1833               flags & MG_FS_DIR ? (int64_t) -1 : (int64_t) size, sz);
1834   }
1835 }
1836
1837 static void listdir(struct mg_connection *c, struct mg_http_message *hm,
1838                     const struct mg_http_serve_opts *opts, char *dir) {
1839   const char *sort_js_code =
1840       "<script>function srt(tb, sc, so, d) {"
1841       "var tr = Array.prototype.slice.call(tb.rows, 0),"
1842       "tr = tr.sort(function (a, b) { var c1 = a.cells[sc], c2 = b.cells[sc],"
1843       "n1 = c1.getAttribute('name'), n2 = c2.getAttribute('name'), "
1844       "t1 = a.cells[2].getAttribute('name'), "
1845       "t2 = b.cells[2].getAttribute('name'); "
1846       "return so * (t1 < 0 && t2 >= 0 ? -1 : t2 < 0 && t1 >= 0 ? 1 : "
1847       "n1 ? parseInt(n2) - parseInt(n1) : "
1848       "c1.textContent.trim().localeCompare(c2.textContent.trim())); });";
1849   const char *sort_js_code2 =
1850       "for (var i = 0; i < tr.length; i++) tb.appendChild(tr[i]); "
1851       "if (!d) window.location.hash = ('sc=' + sc + '&so=' + so); "
1852       "};"
1853       "window.onload = function() {"
1854       "var tb = document.getElementById('tb');"
1855       "var m = /sc=([012]).so=(1|-1)/.exec(window.location.hash) || [0, 2, 1];"
1856       "var sc = m[1], so = m[2]; document.onclick = function(ev) { "
1857       "var c = ev.target.rel; if (c) {if (c == sc) so *= -1; srt(tb, c, so); "
1858       "sc = c; ev.preventDefault();}};"
1859       "srt(tb, sc, so, true);"
1860       "}"
1861       "</script>";
1862   struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
1863   struct printdirentrydata d = {c, hm, opts, dir};
1864   char tmp[10], buf[MG_PATH_MAX];
1865   size_t off, n;
1866   int len = mg_url_decode(hm->uri.ptr, hm->uri.len, buf, sizeof(buf), 0);
1867   struct mg_str uri = len > 0 ? mg_str_n(buf, (size_t) len) : hm->uri;
1868
1869   mg_printf(c,
1870             "HTTP/1.1 200 OK\r\n"
1871             "Content-Type: text/html; charset=utf-8\r\n"
1872             "%s"
1873             "Content-Length:         \r\n\r\n",
1874             opts->extra_headers == NULL ? "" : opts->extra_headers);
1875   off = c->send.len;  // Start of body
1876   mg_printf(c,
1877             "<!DOCTYPE html><html><head><title>Index of %.*s</title>%s%s"
1878             "<style>th,td {text-align: left; padding-right: 1em; "
1879             "font-family: monospace; }</style></head>"
1880             "<body><h1>Index of %.*s</h1><table cellpadding=\"0\"><thead>"
1881             "<tr><th><a href=\"#\" rel=\"0\">Name</a></th><th>"
1882             "<a href=\"#\" rel=\"1\">Modified</a></th>"
1883             "<th><a href=\"#\" rel=\"2\">Size</a></th></tr>"
1884             "<tr><td colspan=\"3\"><hr></td></tr>"
1885             "</thead>"
1886             "<tbody id=\"tb\">\n",
1887             (int) uri.len, uri.ptr, sort_js_code, sort_js_code2, (int) uri.len,
1888             uri.ptr);
1889   mg_printf(c, "%s",
1890             "  <tr><td><a href=\"..\">..</a></td>"
1891             "<td name=-1></td><td name=-1>[DIR]</td></tr>\n");
1892
1893   fs->ls(dir, printdirentry, &d);
1894   mg_printf(c,
1895             "</tbody><tfoot><tr><td colspan=\"3\"><hr></td></tr></tfoot>"
1896             "</table><address>Mongoose v.%s</address></body></html>\n",
1897             MG_VERSION);
1898   n = mg_snprintf(tmp, sizeof(tmp), "%lu", (unsigned long) (c->send.len - off));
1899   if (n > sizeof(tmp)) n = 0;
1900   memcpy(c->send.buf + off - 12, tmp, n);  // Set content length
1901   c->is_resp = 0;                          // Mark response end
1902 }
1903
1904 // Resolve requested file into `path` and return its fs->st() result
1905 static int uri_to_path2(struct mg_connection *c, struct mg_http_message *hm,
1906                         struct mg_fs *fs, struct mg_str url, struct mg_str dir,
1907                         char *path, size_t path_size) {
1908   int flags, tmp;
1909   // Append URI to the root_dir, and sanitize it
1910   size_t n = mg_snprintf(path, path_size, "%.*s", (int) dir.len, dir.ptr);
1911   if (n > path_size) n = path_size;
1912   path[path_size - 1] = '\0';
1913   if (n + 2 < path_size) path[n++] = '/', path[n] = '\0';
1914   mg_url_decode(hm->uri.ptr + url.len, hm->uri.len - url.len, path + n,
1915                 path_size - n, 0);
1916   path[path_size - 1] = '\0';  // Double-check
1917   mg_remove_double_dots(path);
1918   n = strlen(path);
1919   while (n > 1 && path[n - 1] == '/') path[--n] = 0;  // Trim trailing slashes
1920   flags = mg_vcmp(&hm->uri, "/") == 0 ? MG_FS_DIR : fs->st(path, NULL, NULL);
1921   MG_VERBOSE(("%lu %.*s -> %s %d", c->id, (int) hm->uri.len, hm->uri.ptr, path,
1922               flags));
1923   if (flags == 0) {
1924     // Do nothing - let's caller decide
1925   } else if ((flags & MG_FS_DIR) && hm->uri.len > 0 &&
1926              hm->uri.ptr[hm->uri.len - 1] != '/') {
1927     mg_printf(c,
1928               "HTTP/1.1 301 Moved\r\n"
1929               "Location: %.*s/\r\n"
1930               "Content-Length: 0\r\n"
1931               "\r\n",
1932               (int) hm->uri.len, hm->uri.ptr);
1933     c->is_resp = 0;
1934     flags = -1;
1935   } else if (flags & MG_FS_DIR) {
1936     if (((mg_snprintf(path + n, path_size - n, "/" MG_HTTP_INDEX) > 0 &&
1937           (tmp = fs->st(path, NULL, NULL)) != 0) ||
1938          (mg_snprintf(path + n, path_size - n, "/index.shtml") > 0 &&
1939           (tmp = fs->st(path, NULL, NULL)) != 0))) {
1940       flags = tmp;
1941     } else if ((mg_snprintf(path + n, path_size - n, "/" MG_HTTP_INDEX ".gz") >
1942                     0 &&
1943                 (tmp = fs->st(path, NULL, NULL)) !=
1944                     0)) {  // check for gzipped index
1945       flags = tmp;
1946       path[n + 1 + strlen(MG_HTTP_INDEX)] =
1947           '\0';  // Remove appended .gz in index file name
1948     } else {
1949       path[n] = '\0';  // Remove appended index file name
1950     }
1951   }
1952   return flags;
1953 }
1954
1955 static int uri_to_path(struct mg_connection *c, struct mg_http_message *hm,
1956                        const struct mg_http_serve_opts *opts, char *path,
1957                        size_t path_size) {
1958   struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
1959   struct mg_str k, v, s = mg_str(opts->root_dir), u = {0, 0}, p = {0, 0};
1960   while (mg_commalist(&s, &k, &v)) {
1961     if (v.len == 0) v = k, k = mg_str("/");
1962     if (hm->uri.len < k.len) continue;
1963     if (mg_strcmp(k, mg_str_n(hm->uri.ptr, k.len)) != 0) continue;
1964     u = k, p = v;
1965   }
1966   return uri_to_path2(c, hm, fs, u, p, path, path_size);
1967 }
1968
1969 void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
1970                        const struct mg_http_serve_opts *opts) {
1971   char path[MG_PATH_MAX];
1972   const char *sp = opts->ssi_pattern;
1973   int flags = uri_to_path(c, hm, opts, path, sizeof(path));
1974   if (flags < 0) {
1975     // Do nothing: the response has already been sent by uri_to_path()
1976   } else if (flags & MG_FS_DIR) {
1977     listdir(c, hm, opts, path);
1978   } else if (flags && sp != NULL &&
1979              mg_globmatch(sp, strlen(sp), path, strlen(path))) {
1980     mg_http_serve_ssi(c, opts->root_dir, path);
1981   } else {
1982     mg_http_serve_file(c, hm, path, opts);
1983   }
1984 }
1985
1986 static bool mg_is_url_safe(int c) {
1987   return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
1988          (c >= 'A' && c <= 'Z') || c == '.' || c == '_' || c == '-' || c == '~';
1989 }
1990
1991 size_t mg_url_encode(const char *s, size_t sl, char *buf, size_t len) {
1992   size_t i, n = 0;
1993   for (i = 0; i < sl; i++) {
1994     int c = *(unsigned char *) &s[i];
1995     if (n + 4 >= len) return 0;
1996     if (mg_is_url_safe(c)) {
1997       buf[n++] = s[i];
1998     } else {
1999       buf[n++] = '%';
2000       mg_hex(&s[i], 1, &buf[n]);
2001       n += 2;
2002     }
2003   }
2004   if (len > 0 && n < len - 1) buf[n] = '\0';  // Null-terminate the destination
2005   if (len > 0) buf[len - 1] = '\0';           // Always.
2006   return n;
2007 }
2008
2009 void mg_http_creds(struct mg_http_message *hm, char *user, size_t userlen,
2010                    char *pass, size_t passlen) {
2011   struct mg_str *v = mg_http_get_header(hm, "Authorization");
2012   user[0] = pass[0] = '\0';
2013   if (v != NULL && v->len > 6 && memcmp(v->ptr, "Basic ", 6) == 0) {
2014     char buf[256];
2015     int n = mg_base64_decode(v->ptr + 6, (int) v->len - 6, buf);
2016     const char *p = (const char *) memchr(buf, ':', n > 0 ? (size_t) n : 0);
2017     if (p != NULL) {
2018       mg_snprintf(user, userlen, "%.*s", (int) (p - buf), buf);
2019       mg_snprintf(pass, passlen, "%.*s", n - (int) (p - buf) - 1, p + 1);
2020     }
2021   } else if (v != NULL && v->len > 7 && memcmp(v->ptr, "Bearer ", 7) == 0) {
2022     mg_snprintf(pass, passlen, "%.*s", (int) v->len - 7, v->ptr + 7);
2023   } else if ((v = mg_http_get_header(hm, "Cookie")) != NULL) {
2024     struct mg_str t = mg_http_get_header_var(*v, mg_str_n("access_token", 12));
2025     if (t.len > 0) mg_snprintf(pass, passlen, "%.*s", (int) t.len, t.ptr);
2026   } else {
2027     mg_http_get_var(&hm->query, "access_token", pass, passlen);
2028   }
2029 }
2030
2031 static struct mg_str stripquotes(struct mg_str s) {
2032   return s.len > 1 && s.ptr[0] == '"' && s.ptr[s.len - 1] == '"'
2033              ? mg_str_n(s.ptr + 1, s.len - 2)
2034              : s;
2035 }
2036
2037 struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v) {
2038   size_t i;
2039   for (i = 0; v.len > 0 && i + v.len + 2 < s.len; i++) {
2040     if (s.ptr[i + v.len] == '=' && memcmp(&s.ptr[i], v.ptr, v.len) == 0) {
2041       const char *p = &s.ptr[i + v.len + 1], *b = p, *x = &s.ptr[s.len];
2042       int q = p < x && *p == '"' ? 1 : 0;
2043       while (p < x &&
2044              (q ? p == b || *p != '"' : *p != ';' && *p != ' ' && *p != ','))
2045         p++;
2046       // MG_INFO(("[%.*s] [%.*s] [%.*s]", (int) s.len, s.ptr, (int) v.len,
2047       // v.ptr, (int) (p - b), b));
2048       return stripquotes(mg_str_n(b, (size_t) (p - b + q)));
2049     }
2050   }
2051   return mg_str_n(NULL, 0);
2052 }
2053
2054 bool mg_http_match_uri(const struct mg_http_message *hm, const char *glob) {
2055   return mg_match(hm->uri, mg_str(glob), NULL);
2056 }
2057
2058 long mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
2059                     struct mg_fs *fs, const char *path, size_t max_size) {
2060   char buf[20] = "0";
2061   long res = 0, offset;
2062   mg_http_get_var(&hm->query, "offset", buf, sizeof(buf));
2063   offset = strtol(buf, NULL, 0);
2064   if (hm->body.len == 0) {
2065     mg_http_reply(c, 200, "", "%ld", res);  // Nothing to write
2066   } else {
2067     struct mg_fd *fd;
2068     size_t current_size = 0;
2069     MG_DEBUG(("%s -> %d bytes @ %ld", path, (int) hm->body.len, offset));
2070     if (offset == 0) fs->rm(path);  // If offset if 0, truncate file
2071     fs->st(path, &current_size, NULL);
2072     if (offset < 0) {
2073       mg_http_reply(c, 400, "", "offset required");
2074       res = -1;
2075     } else if (offset > 0 && current_size != (size_t) offset) {
2076       mg_http_reply(c, 400, "", "%s: offset mismatch", path);
2077       res = -2;
2078     } else if ((size_t) offset + hm->body.len > max_size) {
2079       mg_http_reply(c, 400, "", "%s: over max size of %lu", path,
2080                     (unsigned long) max_size);
2081       res = -3;
2082     } else if ((fd = mg_fs_open(fs, path, MG_FS_WRITE)) == NULL) {
2083       mg_http_reply(c, 400, "", "open(%s): %d", path, errno);
2084       res = -4;
2085     } else {
2086       res = offset + (long) fs->wr(fd->fd, hm->body.ptr, hm->body.len);
2087       mg_fs_close(fd);
2088       mg_http_reply(c, 200, "", "%ld", res);
2089     }
2090   }
2091   return res;
2092 }
2093
2094 int mg_http_status(const struct mg_http_message *hm) {
2095   return atoi(hm->uri.ptr);
2096 }
2097
2098 // If a server sends data to the client using chunked encoding, Mongoose strips
2099 // off the chunking prefix (hex length and \r\n) and suffix (\r\n), appends the
2100 // stripped data to the body, and fires the MG_EV_HTTP_CHUNK event.  When zero
2101 // chunk is received, we fire MG_EV_HTTP_MSG, and the body already has all
2102 // chunking prefixes/suffixes stripped.
2103 //
2104 // If a server sends data without chunked encoding, we also fire a series of
2105 // MG_EV_HTTP_CHUNK events for every received piece of data, and then we fire
2106 // MG_EV_HTTP_MSG event in the end.
2107 //
2108 // We track total processed length in the c->pfn_data, which is a void *
2109 // pointer: we store a size_t value there.
2110 static bool getchunk(struct mg_str s, size_t *prefixlen, size_t *datalen) {
2111   size_t i = 0, n;
2112   while (i < s.len && s.ptr[i] != '\r' && s.ptr[i] != '\n') i++;
2113   n = mg_unhexn(s.ptr, i);
2114   // MG_INFO(("%d %d", (int) (i + n + 4), (int) s.len));
2115   if (s.len < i + n + 4) return false;  // Chunk not yet fully buffered
2116   if (s.ptr[i] != '\r' || s.ptr[i + 1] != '\n') return false;
2117   if (s.ptr[i + n + 2] != '\r' || s.ptr[i + n + 3] != '\n') return false;
2118   *prefixlen = i + 2;
2119   *datalen = n;
2120   return true;
2121 }
2122
2123 static bool mg_is_chunked(struct mg_http_message *hm) {
2124   const char *needle = "chunked";
2125   struct mg_str *te = mg_http_get_header(hm, "Transfer-Encoding");
2126   return te != NULL && mg_vcasecmp(te, needle) == 0;
2127 }
2128
2129 void mg_http_delete_chunk(struct mg_connection *c, struct mg_http_message *hm) {
2130   size_t ofs = (size_t) (hm->chunk.ptr - (char *) c->recv.buf);
2131   mg_iobuf_del(&c->recv, ofs, hm->chunk.len);
2132   c->pfn_data = (void *) ((size_t) c->pfn_data | MG_DMARK);
2133 }
2134
2135 static void deliver_chunked_chunks(struct mg_connection *c, size_t hlen,
2136                                    struct mg_http_message *hm, bool *next) {
2137   //  |  ... headers ... | HEXNUM\r\n ..data.. \r\n | ......
2138   //  +------------------+--------------------------+----
2139   //  |      hlen        |           chunk1         | ......
2140   char *buf = (char *) &c->recv.buf[hlen], *p = buf;
2141   size_t len = c->recv.len - hlen;
2142   size_t processed = ((size_t) c->pfn_data) & ~MG_DMARK;
2143   size_t mark, pl, dl, del = 0, ofs = 0;
2144   bool last = false;
2145   if (processed <= len) len -= processed, buf += processed;
2146   while (!last && getchunk(mg_str_n(buf + ofs, len - ofs), &pl, &dl)) {
2147     size_t saved = c->recv.len;
2148     memmove(p + processed, buf + ofs + pl, dl);
2149     // MG_INFO(("P2 [%.*s]", (int) (processed + dl), p));
2150     hm->chunk = mg_str_n(p + processed, dl);
2151     mg_call(c, MG_EV_HTTP_CHUNK, hm);
2152     ofs += pl + dl + 2, del += pl + 2;  // 2 is for \r\n suffix
2153     processed += dl;
2154     if (c->recv.len != saved) processed -= dl, buf -= dl;
2155     // mg_hexdump(c->recv.buf, hlen + processed);
2156     last = (dl == 0);
2157   }
2158   mg_iobuf_del(&c->recv, hlen + processed, del);
2159   mark = ((size_t) c->pfn_data) & MG_DMARK;
2160   c->pfn_data = (void *) (processed | mark);
2161   if (last) {
2162     hm->body.len = processed;
2163     hm->message.len = hlen + processed;
2164     c->pfn_data = NULL;
2165     if (mark) mg_iobuf_del(&c->recv, 0, hlen), *next = true;
2166     // MG_INFO(("LAST, mark: %lx", mark));
2167     // mg_hexdump(c->recv.buf, c->recv.len);
2168   }
2169 }
2170
2171 static void deliver_normal_chunks(struct mg_connection *c, size_t hlen,
2172                                   struct mg_http_message *hm, bool *next) {
2173   size_t left, processed = ((size_t) c->pfn_data) & ~MG_DMARK;
2174   size_t deleted = ((size_t) c->pfn_data) & MG_DMARK;
2175   hm->chunk = mg_str_n((char *) &c->recv.buf[hlen], c->recv.len - hlen);
2176   if (processed <= hm->chunk.len && !deleted) {
2177     hm->chunk.len -= processed;
2178     hm->chunk.ptr += processed;
2179   }
2180   left = hm->body.len < processed ? 0 : hm->body.len - processed;
2181   if (hm->chunk.len > left) hm->chunk.len = left;
2182   if (hm->chunk.len > 0) mg_call(c, MG_EV_HTTP_CHUNK, hm);
2183   processed += hm->chunk.len;
2184   deleted = ((size_t) c->pfn_data) & MG_DMARK;  // Re-evaluate after user call
2185   if (processed >= hm->body.len) {              // Last, 0-len chunk
2186     hm->chunk.len = 0;                          // Reset length
2187     mg_call(c, MG_EV_HTTP_CHUNK, hm);           // Call user handler
2188     c->pfn_data = NULL;                         // Reset processed counter
2189     if (processed && deleted) mg_iobuf_del(&c->recv, 0, hlen), *next = true;
2190   } else {
2191     c->pfn_data = (void *) (processed | deleted);  // if it is set
2192   }
2193 }
2194
2195 static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
2196   if (ev == MG_EV_READ || ev == MG_EV_CLOSE) {
2197     struct mg_http_message hm;
2198     // mg_hexdump(c->recv.buf, c->recv.len);
2199     while (c->recv.buf != NULL && c->recv.len > 0) {
2200       bool next = false;
2201       int hlen = mg_http_parse((char *) c->recv.buf, c->recv.len, &hm);
2202       if (hlen < 0) {
2203         mg_error(c, "HTTP parse:\n%.*s", (int) c->recv.len, c->recv.buf);
2204         break;
2205       }
2206       if (c->is_resp) break;           // Response is still generated
2207       if (hlen == 0) break;            // Request is not buffered yet
2208       if (ev == MG_EV_CLOSE) {         // If client did not set Content-Length
2209         hm.message.len = c->recv.len;  // and closes now, deliver a MSG
2210         hm.body.len = hm.message.len - (size_t) (hm.body.ptr - hm.message.ptr);
2211       }
2212       if (mg_is_chunked(&hm)) {
2213         deliver_chunked_chunks(c, (size_t) hlen, &hm, &next);
2214       } else {
2215         deliver_normal_chunks(c, (size_t) hlen, &hm, &next);
2216       }
2217       if (next) continue;  // Chunks & request were deleted
2218       //  Chunk events are delivered. If we have full body, deliver MSG
2219       if (c->recv.len < hm.message.len) break;
2220       if (c->is_accepted) c->is_resp = 1;  // Start generating response
2221       mg_call(c, MG_EV_HTTP_MSG, &hm);     // User handler can clear is_resp
2222       mg_iobuf_del(&c->recv, 0, hm.message.len);
2223     }
2224   }
2225   (void) evd, (void) fnd;
2226 }
2227
2228 static void mg_hfn(struct mg_connection *c, int ev, void *ev_data, void *fnd) {
2229   if (ev == MG_EV_HTTP_MSG) {
2230     struct mg_http_message *hm = (struct mg_http_message *) ev_data;
2231     if (mg_http_match_uri(hm, "/quit")) {
2232       mg_http_reply(c, 200, "", "ok\n");
2233       c->is_draining = 1;
2234       c->data[0] = 'X';
2235     } else if (mg_http_match_uri(hm, "/debug")) {
2236       int level = (int) mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG);
2237       mg_log_set(level);
2238       mg_http_reply(c, 200, "", "Debug level set to %d\n", level);
2239     } else {
2240       mg_http_reply(c, 200, "", "hi\n");
2241     }
2242   } else if (ev == MG_EV_CLOSE) {
2243     if (c->data[0] == 'X') *(bool *) fnd = true;
2244   }
2245 }
2246
2247 void mg_hello(const char *url) {
2248   struct mg_mgr mgr;
2249   bool done = false;
2250   mg_mgr_init(&mgr);
2251   if (mg_http_listen(&mgr, url, mg_hfn, &done) == NULL) done = true;
2252   while (done == false) mg_mgr_poll(&mgr, 100);
2253   mg_mgr_free(&mgr);
2254 }
2255
2256 struct mg_connection *mg_http_connect(struct mg_mgr *mgr, const char *url,
2257                                       mg_event_handler_t fn, void *fn_data) {
2258   struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
2259   if (c != NULL) c->pfn = http_cb;
2260   return c;
2261 }
2262
2263 struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url,
2264                                      mg_event_handler_t fn, void *fn_data) {
2265   struct mg_connection *c = mg_listen(mgr, url, fn, fn_data);
2266   if (c != NULL) c->pfn = http_cb;
2267   return c;
2268 }
2269
2270 #ifdef MG_ENABLE_LINES
2271 #line 1 "src/iobuf.c"
2272 #endif
2273
2274
2275
2276
2277 // Not using memset for zeroing memory, cause it can be dropped by compiler
2278 // See https://github.com/cesanta/mongoose/pull/1265
2279 static void zeromem(volatile unsigned char *buf, size_t len) {
2280   if (buf != NULL) {
2281     while (len--) *buf++ = 0;
2282   }
2283 }
2284
2285 static size_t roundup(size_t size, size_t align) {
2286   return align == 0 ? size : (size + align - 1) / align * align;
2287 }
2288
2289 int mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) {
2290   int ok = 1;
2291   new_size = roundup(new_size, io->align);
2292   if (new_size == 0) {
2293     zeromem(io->buf, io->size);
2294     free(io->buf);
2295     io->buf = NULL;
2296     io->len = io->size = 0;
2297   } else if (new_size != io->size) {
2298     // NOTE(lsm): do not use realloc here. Use calloc/free only, to ease the
2299     // porting to some obscure platforms like FreeRTOS
2300     void *p = calloc(1, new_size);
2301     if (p != NULL) {
2302       size_t len = new_size < io->len ? new_size : io->len;
2303       if (len > 0 && io->buf != NULL) memmove(p, io->buf, len);
2304       zeromem(io->buf, io->size);
2305       free(io->buf);
2306       io->buf = (unsigned char *) p;
2307       io->size = new_size;
2308     } else {
2309       ok = 0;
2310       MG_ERROR(("%lld->%lld", (uint64_t) io->size, (uint64_t) new_size));
2311     }
2312   }
2313   return ok;
2314 }
2315
2316 int mg_iobuf_init(struct mg_iobuf *io, size_t size, size_t align) {
2317   io->buf = NULL;
2318   io->align = align;
2319   io->size = io->len = 0;
2320   return mg_iobuf_resize(io, size);
2321 }
2322
2323 size_t mg_iobuf_add(struct mg_iobuf *io, size_t ofs, const void *buf,
2324                     size_t len) {
2325   size_t new_size = roundup(io->len + len, io->align);
2326   mg_iobuf_resize(io, new_size);      // Attempt to resize
2327   if (new_size != io->size) len = 0;  // Resize failure, append nothing
2328   if (ofs < io->len) memmove(io->buf + ofs + len, io->buf + ofs, io->len - ofs);
2329   if (buf != NULL) memmove(io->buf + ofs, buf, len);
2330   if (ofs > io->len) io->len += ofs - io->len;
2331   io->len += len;
2332   return len;
2333 }
2334
2335 size_t mg_iobuf_del(struct mg_iobuf *io, size_t ofs, size_t len) {
2336   if (ofs > io->len) ofs = io->len;
2337   if (ofs + len > io->len) len = io->len - ofs;
2338   if (io->buf) memmove(io->buf + ofs, io->buf + ofs + len, io->len - ofs - len);
2339   if (io->buf) zeromem(io->buf + io->len - len, len);
2340   io->len -= len;
2341   return len;
2342 }
2343
2344 void mg_iobuf_free(struct mg_iobuf *io) {
2345   mg_iobuf_resize(io, 0);
2346 }
2347
2348 #ifdef MG_ENABLE_LINES
2349 #line 1 "src/json.c"
2350 #endif
2351
2352
2353
2354
2355 static const char *escapeseq(int esc) {
2356   return esc ? "\b\f\n\r\t\\\"" : "bfnrt\\\"";
2357 }
2358
2359 static char json_esc(int c, int esc) {
2360   const char *p, *esc1 = escapeseq(esc), *esc2 = escapeseq(!esc);
2361   for (p = esc1; *p != '\0'; p++) {
2362     if (*p == c) return esc2[p - esc1];
2363   }
2364   return 0;
2365 }
2366
2367 static int mg_pass_string(const char *s, int len) {
2368   int i;
2369   for (i = 0; i < len; i++) {
2370     if (s[i] == '\\' && i + 1 < len && json_esc(s[i + 1], 1)) {
2371       i++;
2372     } else if (s[i] == '\0') {
2373       return MG_JSON_INVALID;
2374     } else if (s[i] == '"') {
2375       return i;
2376     }
2377   }
2378   return MG_JSON_INVALID;
2379 }
2380
2381 static double mg_atod(const char *p, int len, int *numlen) {
2382   double d = 0.0;
2383   int i = 0, sign = 1;
2384
2385   // Sign
2386   if (i < len && *p == '-') {
2387     sign = -1, i++;
2388   } else if (i < len && *p == '+') {
2389     i++;
2390   }
2391
2392   // Decimal
2393   for (; i < len && p[i] >= '0' && p[i] <= '9'; i++) {
2394     d *= 10.0;
2395     d += p[i] - '0';
2396   }
2397   d *= sign;
2398
2399   // Fractional
2400   if (i < len && p[i] == '.') {
2401     double frac = 0.0, base = 0.1;
2402     i++;
2403     for (; i < len && p[i] >= '0' && p[i] <= '9'; i++) {
2404       frac += base * (p[i] - '0');
2405       base /= 10.0;
2406     }
2407     d += frac * sign;
2408   }
2409
2410   // Exponential
2411   if (i < len && (p[i] == 'e' || p[i] == 'E')) {
2412     int j, exp = 0, minus = 0;
2413     i++;
2414     if (i < len && p[i] == '-') minus = 1, i++;
2415     if (i < len && p[i] == '+') i++;
2416     while (i < len && p[i] >= '0' && p[i] <= '9' && exp < 308)
2417       exp = exp * 10 + (p[i++] - '0');
2418     if (minus) exp = -exp;
2419     for (j = 0; j < exp; j++) d *= 10.0;
2420     for (j = 0; j < -exp; j++) d /= 10.0;
2421   }
2422
2423   if (numlen != NULL) *numlen = i;
2424   return d;
2425 }
2426
2427 int mg_json_get(struct mg_str json, const char *path, int *toklen) {
2428   const char *s = json.ptr;
2429   int len = (int) json.len;
2430   enum { S_VALUE, S_KEY, S_COLON, S_COMMA_OR_EOO } expecting = S_VALUE;
2431   unsigned char nesting[MG_JSON_MAX_DEPTH];
2432   int i = 0;             // Current offset in `s`
2433   int j = 0;             // Offset in `s` we're looking for (return value)
2434   int depth = 0;         // Current depth (nesting level)
2435   int ed = 0;            // Expected depth
2436   int pos = 1;           // Current position in `path`
2437   int ci = -1, ei = -1;  // Current and expected index in array
2438
2439   if (toklen) *toklen = 0;
2440   if (path[0] != '$') return MG_JSON_INVALID;
2441
2442 #define MG_CHECKRET(x)                                  \
2443   do {                                                  \
2444     if (depth == ed && path[pos] == '\0' && ci == ei) { \
2445       if (toklen) *toklen = i - j + 1;                  \
2446       return j;                                         \
2447     }                                                   \
2448   } while (0)
2449
2450 // In the ascii table, the distance between `[` and `]` is 2.
2451 // Ditto for `{` and `}`. Hence +2 in the code below.
2452 #define MG_EOO(x)                                            \
2453   do {                                                       \
2454     if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND;   \
2455     if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
2456     depth--;                                                 \
2457     MG_CHECKRET(x);                                          \
2458   } while (0)
2459
2460   for (i = 0; i < len; i++) {
2461     unsigned char c = ((unsigned char *) s)[i];
2462     if (c == ' ' || c == '\t' || c == '\n' || c == '\r') continue;
2463     switch (expecting) {
2464       case S_VALUE:
2465         // p("V %s [%.*s] %d %d %d %d\n", path, pos, path, depth, ed, ci, ei);
2466         if (depth == ed) j = i;
2467         if (c == '{') {
2468           if (depth >= (int) sizeof(nesting)) return MG_JSON_TOO_DEEP;
2469           if (depth == ed && path[pos] == '.' && ci == ei) {
2470             // If we start the object, reset array indices
2471             ed++, pos++, ci = ei = -1;
2472           }
2473           nesting[depth++] = c;
2474           expecting = S_KEY;
2475           break;
2476         } else if (c == '[') {
2477           if (depth >= (int) sizeof(nesting)) return MG_JSON_TOO_DEEP;
2478           if (depth == ed && path[pos] == '[' && ei == ci) {
2479             ed++, pos++, ci = 0;
2480             for (ei = 0; path[pos] != ']' && path[pos] != '\0'; pos++) {
2481               ei *= 10;
2482               ei += path[pos] - '0';
2483             }
2484             if (path[pos] != 0) pos++;
2485           }
2486           nesting[depth++] = c;
2487           break;
2488         } else if (c == ']' && depth > 0) {  // Empty array
2489           MG_EOO(']');
2490         } else if (c == 't' && i + 3 < len && memcmp(&s[i], "true", 4) == 0) {
2491           i += 3;
2492         } else if (c == 'n' && i + 3 < len && memcmp(&s[i], "null", 4) == 0) {
2493           i += 3;
2494         } else if (c == 'f' && i + 4 < len && memcmp(&s[i], "false", 5) == 0) {
2495           i += 4;
2496         } else if (c == '-' || ((c >= '0' && c <= '9'))) {
2497           int numlen = 0;
2498           mg_atod(&s[i], len - i, &numlen);
2499           i += numlen - 1;
2500         } else if (c == '"') {
2501           int n = mg_pass_string(&s[i + 1], len - i - 1);
2502           if (n < 0) return n;
2503           i += n + 1;
2504         } else {
2505           return MG_JSON_INVALID;
2506         }
2507         MG_CHECKRET('V');
2508         if (depth == ed && ei >= 0) ci++;
2509         expecting = S_COMMA_OR_EOO;
2510         break;
2511
2512       case S_KEY:
2513         if (c == '"') {
2514           int n = mg_pass_string(&s[i + 1], len - i - 1);
2515           if (n < 0) return n;
2516           if (i + 1 + n >= len) return MG_JSON_NOT_FOUND;
2517           if (depth < ed) return MG_JSON_NOT_FOUND;
2518           if (depth == ed && path[pos - 1] != '.') return MG_JSON_NOT_FOUND;
2519           // printf("K %s [%.*s] [%.*s] %d %d %d\n", path, pos, path, n,
2520           //  &s[i + 1], n, depth, ed);
2521           // NOTE(cpq): in the check sequence below is important.
2522           // strncmp() must go first: it fails fast if the remaining length of
2523           // the path is smaller than `n`.
2524           if (depth == ed && path[pos - 1] == '.' &&
2525               strncmp(&s[i + 1], &path[pos], (size_t) n) == 0 &&
2526               (path[pos + n] == '\0' || path[pos + n] == '.' ||
2527                path[pos + n] == '[')) {
2528             pos += n;
2529           }
2530           i += n + 1;
2531           expecting = S_COLON;
2532         } else if (c == '}') {  // Empty object
2533           MG_EOO('}');
2534           expecting = S_COMMA_OR_EOO;
2535         } else {
2536           return MG_JSON_INVALID;
2537         }
2538         break;
2539
2540       case S_COLON:
2541         if (c == ':') {
2542           expecting = S_VALUE;
2543         } else {
2544           return MG_JSON_INVALID;
2545         }
2546         break;
2547
2548       case S_COMMA_OR_EOO:
2549         if (depth <= 0) {
2550           return MG_JSON_INVALID;
2551         } else if (c == ',') {
2552           expecting = (nesting[depth - 1] == '{') ? S_KEY : S_VALUE;
2553         } else if (c == ']' || c == '}') {
2554           MG_EOO('O');
2555           if (depth == ed && ei >= 0) ci++;
2556         } else {
2557           return MG_JSON_INVALID;
2558         }
2559         break;
2560     }
2561   }
2562   return MG_JSON_NOT_FOUND;
2563 }
2564
2565 bool mg_json_get_num(struct mg_str json, const char *path, double *v) {
2566   int n, toklen, found = 0;
2567   if ((n = mg_json_get(json, path, &toklen)) >= 0 &&
2568       (json.ptr[n] == '-' || (json.ptr[n] >= '0' && json.ptr[n] <= '9'))) {
2569     if (v != NULL) *v = mg_atod(json.ptr + n, toklen, NULL);
2570     found = 1;
2571   }
2572   return found;
2573 }
2574
2575 bool mg_json_get_bool(struct mg_str json, const char *path, bool *v) {
2576   int found = 0, off = mg_json_get(json, path, NULL);
2577   if (off >= 0 && (json.ptr[off] == 't' || json.ptr[off] == 'f')) {
2578     if (v != NULL) *v = json.ptr[off] == 't';
2579     found = 1;
2580   }
2581   return found;
2582 }
2583
2584 static bool json_unescape(const char *s, size_t len, char *to, size_t n) {
2585   size_t i, j;
2586   for (i = 0, j = 0; i < len && j < n; i++, j++) {
2587     if (s[i] == '\\' && i + 5 < len && s[i + 1] == 'u') {
2588       //  \uXXXX escape. We could process a simple one-byte chars
2589       // \u00xx from the ASCII range. More complex chars would require
2590       // dragging in a UTF8 library, which is too much for us
2591       if (s[i + 2] != '0' || s[i + 3] != '0') return false;  // Give up
2592       ((unsigned char *) to)[j] = (unsigned char) mg_unhexn(s + i + 4, 2);
2593
2594       i += 5;
2595     } else if (s[i] == '\\' && i + 1 < len) {
2596       char c = json_esc(s[i + 1], 0);
2597       if (c == 0) return false;
2598       to[j] = c;
2599       i++;
2600     } else {
2601       to[j] = s[i];
2602     }
2603   }
2604   if (j >= n) return false;
2605   if (n > 0) to[j] = '\0';
2606   return true;
2607 }
2608
2609 char *mg_json_get_str(struct mg_str json, const char *path) {
2610   char *result = NULL;
2611   int len = 0, off = mg_json_get(json, path, &len);
2612   if (off >= 0 && len > 1 && json.ptr[off] == '"') {
2613     if ((result = (char *) calloc(1, (size_t) len)) != NULL &&
2614         !json_unescape(json.ptr + off + 1, (size_t) (len - 2), result,
2615                        (size_t) len)) {
2616       free(result);
2617       result = NULL;
2618     }
2619   }
2620   return result;
2621 }
2622
2623 char *mg_json_get_b64(struct mg_str json, const char *path, int *slen) {
2624   char *result = NULL;
2625   int len = 0, off = mg_json_get(json, path, &len);
2626   if (off >= 0 && json.ptr[off] == '"' && len > 1 &&
2627       (result = (char *) calloc(1, (size_t) len)) != NULL) {
2628     int k = mg_base64_decode(json.ptr + off + 1, len - 2, result);
2629     if (slen != NULL) *slen = k;
2630   }
2631   return result;
2632 }
2633
2634 char *mg_json_get_hex(struct mg_str json, const char *path, int *slen) {
2635   char *result = NULL;
2636   int len = 0, off = mg_json_get(json, path, &len);
2637   if (off >= 0 && json.ptr[off] == '"' && len > 1 &&
2638       (result = (char *) calloc(1, (size_t) len / 2)) != NULL) {
2639     mg_unhex(json.ptr + off + 1, (size_t) (len - 2), (uint8_t *) result);
2640     result[len / 2 - 1] = '\0';
2641     if (slen != NULL) *slen = len / 2 - 1;
2642   }
2643   return result;
2644 }
2645
2646 long mg_json_get_long(struct mg_str json, const char *path, long dflt) {
2647   double dv;
2648   long result = dflt;
2649   if (mg_json_get_num(json, path, &dv)) result = (long) dv;
2650   return result;
2651 }
2652
2653 #ifdef MG_ENABLE_LINES
2654 #line 1 "src/log.c"
2655 #endif
2656
2657
2658
2659
2660
2661 static int s_level = MG_LL_INFO;
2662 static mg_pfn_t s_log_func = mg_pfn_stdout;
2663 static void *s_log_func_param = NULL;
2664
2665 void mg_log_set_fn(mg_pfn_t fn, void *param) {
2666   s_log_func = fn;
2667   s_log_func_param = param;
2668 }
2669
2670 static void logc(unsigned char c) {
2671   s_log_func((char) c, s_log_func_param);
2672 }
2673
2674 static void logs(const char *buf, size_t len) {
2675   size_t i;
2676   for (i = 0; i < len; i++) logc(((unsigned char *) buf)[i]);
2677 }
2678
2679 void mg_log_set(int log_level) {
2680   MG_DEBUG(("Setting log level to %d", log_level));
2681   s_level = log_level;
2682 }
2683
2684 bool mg_log_prefix(int level, const char *file, int line, const char *fname) {
2685   if (level <= s_level) {
2686     const char *p = strrchr(file, '/');
2687     char buf[41];
2688     size_t n;
2689     if (p == NULL) p = strrchr(file, '\\');
2690     n = mg_snprintf(buf, sizeof(buf), "%-6llx %d %s:%d:%s", mg_millis(), level,
2691                     p == NULL ? file : p + 1, line, fname);
2692     if (n > sizeof(buf) - 2) n = sizeof(buf) - 2;
2693     while (n < sizeof(buf)) buf[n++] = ' ';
2694     logs(buf, n - 1);
2695     return true;
2696   } else {
2697     return false;
2698   }
2699 }
2700
2701 void mg_log(const char *fmt, ...) {
2702   va_list ap;
2703   va_start(ap, fmt);
2704   mg_vxprintf(s_log_func, s_log_func_param, fmt, &ap);
2705   va_end(ap);
2706   logc((unsigned char) '\n');
2707 }
2708
2709 static unsigned char nibble(unsigned c) {
2710   return (unsigned char) (c < 10 ? c + '0' : c + 'W');
2711 }
2712
2713 #define ISPRINT(x) ((x) >= ' ' && (x) <= '~')
2714 void mg_hexdump(const void *buf, size_t len) {
2715   const unsigned char *p = (const unsigned char *) buf;
2716   unsigned char ascii[16], alen = 0;
2717   size_t i;
2718   for (i = 0; i < len; i++) {
2719     if ((i % 16) == 0) {
2720       // Print buffered ascii chars
2721       if (i > 0) logs("  ", 2), logs((char *) ascii, 16), logc('\n'), alen = 0;
2722       // Print hex address, then \t
2723       logc(nibble((i >> 12) & 15)), logc(nibble((i >> 8) & 15)),
2724           logc(nibble((i >> 4) & 15)), logc('0'), logs("   ", 3);
2725     }
2726     logc(nibble(p[i] >> 4)), logc(nibble(p[i] & 15));  // Two nibbles, e.g. c5
2727     logc(' ');                                         // Space after hex number
2728     ascii[alen++] = ISPRINT(p[i]) ? p[i] : '.';        // Add to the ascii buf
2729   }
2730   while (alen < 16) logs("   ", 3), ascii[alen++] = ' ';
2731   logs("  ", 2), logs((char *) ascii, 16), logc('\n');
2732 }
2733
2734 #ifdef MG_ENABLE_LINES
2735 #line 1 "src/md5.c"
2736 #endif
2737
2738
2739
2740 #if defined(MG_ENABLE_MD5) && MG_ENABLE_MD5
2741
2742 static void mg_byte_reverse(unsigned char *buf, unsigned longs) {
2743   if (MG_BIG_ENDIAN) {
2744     do {
2745       uint32_t t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
2746                    ((unsigned) buf[1] << 8 | buf[0]);
2747       *(uint32_t *) buf = t;
2748       buf += 4;
2749     } while (--longs);
2750   } else {
2751     (void) buf, (void) longs;  // Little endian. Do nothing
2752   }
2753 }
2754
2755 #define F1(x, y, z) (z ^ (x & (y ^ z)))
2756 #define F2(x, y, z) F1(z, x, y)
2757 #define F3(x, y, z) (x ^ y ^ z)
2758 #define F4(x, y, z) (y ^ (x | ~z))
2759
2760 #define MD5STEP(f, w, x, y, z, data, s) \
2761   (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
2762
2763 /*
2764  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
2765  * initialization constants.
2766  */
2767 void mg_md5_init(mg_md5_ctx *ctx) {
2768   ctx->buf[0] = 0x67452301;
2769   ctx->buf[1] = 0xefcdab89;
2770   ctx->buf[2] = 0x98badcfe;
2771   ctx->buf[3] = 0x10325476;
2772
2773   ctx->bits[0] = 0;
2774   ctx->bits[1] = 0;
2775 }
2776
2777 static void mg_md5_transform(uint32_t buf[4], uint32_t const in[16]) {
2778   uint32_t a, b, c, d;
2779
2780   a = buf[0];
2781   b = buf[1];
2782   c = buf[2];
2783   d = buf[3];
2784
2785   MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
2786   MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
2787   MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
2788   MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
2789   MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
2790   MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
2791   MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
2792   MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
2793   MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
2794   MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
2795   MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
2796   MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
2797   MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
2798   MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
2799   MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
2800   MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
2801
2802   MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
2803   MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
2804   MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
2805   MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
2806   MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
2807   MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
2808   MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
2809   MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
2810   MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
2811   MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
2812   MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
2813   MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
2814   MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
2815   MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
2816   MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
2817   MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
2818
2819   MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
2820   MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
2821   MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
2822   MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
2823   MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
2824   MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
2825   MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
2826   MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
2827   MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
2828   MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
2829   MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
2830   MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
2831   MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
2832   MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
2833   MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
2834   MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
2835
2836   MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
2837   MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
2838   MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
2839   MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
2840   MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
2841   MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
2842   MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
2843   MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
2844   MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
2845   MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
2846   MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
2847   MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
2848   MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
2849   MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
2850   MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
2851   MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
2852
2853   buf[0] += a;
2854   buf[1] += b;
2855   buf[2] += c;
2856   buf[3] += d;
2857 }
2858
2859 void mg_md5_update(mg_md5_ctx *ctx, const unsigned char *buf, size_t len) {
2860   uint32_t t;
2861
2862   t = ctx->bits[0];
2863   if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++;
2864   ctx->bits[1] += (uint32_t) len >> 29;
2865
2866   t = (t >> 3) & 0x3f;
2867
2868   if (t) {
2869     unsigned char *p = (unsigned char *) ctx->in + t;
2870
2871     t = 64 - t;
2872     if (len < t) {
2873       memcpy(p, buf, len);
2874       return;
2875     }
2876     memcpy(p, buf, t);
2877     mg_byte_reverse(ctx->in, 16);
2878     mg_md5_transform(ctx->buf, (uint32_t *) ctx->in);
2879     buf += t;
2880     len -= t;
2881   }
2882
2883   while (len >= 64) {
2884     memcpy(ctx->in, buf, 64);
2885     mg_byte_reverse(ctx->in, 16);
2886     mg_md5_transform(ctx->buf, (uint32_t *) ctx->in);
2887     buf += 64;
2888     len -= 64;
2889   }
2890
2891   memcpy(ctx->in, buf, len);
2892 }
2893
2894 void mg_md5_final(mg_md5_ctx *ctx, unsigned char digest[16]) {
2895   unsigned count;
2896   unsigned char *p;
2897   uint32_t *a;
2898
2899   count = (ctx->bits[0] >> 3) & 0x3F;
2900
2901   p = ctx->in + count;
2902   *p++ = 0x80;
2903   count = 64 - 1 - count;
2904   if (count < 8) {
2905     memset(p, 0, count);
2906     mg_byte_reverse(ctx->in, 16);
2907     mg_md5_transform(ctx->buf, (uint32_t *) ctx->in);
2908     memset(ctx->in, 0, 56);
2909   } else {
2910     memset(p, 0, count - 8);
2911   }
2912   mg_byte_reverse(ctx->in, 14);
2913
2914   a = (uint32_t *) ctx->in;
2915   a[14] = ctx->bits[0];
2916   a[15] = ctx->bits[1];
2917
2918   mg_md5_transform(ctx->buf, (uint32_t *) ctx->in);
2919   mg_byte_reverse((unsigned char *) ctx->buf, 4);
2920   memcpy(digest, ctx->buf, 16);
2921   memset((char *) ctx, 0, sizeof(*ctx));
2922 }
2923 #endif
2924
2925 #ifdef MG_ENABLE_LINES
2926 #line 1 "src/mqtt.c"
2927 #endif
2928
2929
2930
2931
2932
2933
2934
2935
2936 #define MQTT_CLEAN_SESSION 0x02
2937 #define MQTT_HAS_WILL 0x04
2938 #define MQTT_WILL_RETAIN 0x20
2939 #define MQTT_HAS_PASSWORD 0x40
2940 #define MQTT_HAS_USER_NAME 0x80
2941
2942 struct mg_mqtt_pmap {
2943   uint8_t id;
2944   uint8_t type;
2945 };
2946
2947 static const struct mg_mqtt_pmap s_prop_map[] = {
2948     {MQTT_PROP_PAYLOAD_FORMAT_INDICATOR, MQTT_PROP_TYPE_BYTE},
2949     {MQTT_PROP_MESSAGE_EXPIRY_INTERVAL, MQTT_PROP_TYPE_INT},
2950     {MQTT_PROP_CONTENT_TYPE, MQTT_PROP_TYPE_STRING},
2951     {MQTT_PROP_RESPONSE_TOPIC, MQTT_PROP_TYPE_STRING},
2952     {MQTT_PROP_CORRELATION_DATA, MQTT_PROP_TYPE_BINARY_DATA},
2953     {MQTT_PROP_SUBSCRIPTION_IDENTIFIER, MQTT_PROP_TYPE_VARIABLE_INT},
2954     {MQTT_PROP_SESSION_EXPIRY_INTERVAL, MQTT_PROP_TYPE_INT},
2955     {MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER, MQTT_PROP_TYPE_STRING},
2956     {MQTT_PROP_SERVER_KEEP_ALIVE, MQTT_PROP_TYPE_SHORT},
2957     {MQTT_PROP_AUTHENTICATION_METHOD, MQTT_PROP_TYPE_STRING},
2958     {MQTT_PROP_AUTHENTICATION_DATA, MQTT_PROP_TYPE_BINARY_DATA},
2959     {MQTT_PROP_REQUEST_PROBLEM_INFORMATION, MQTT_PROP_TYPE_BYTE},
2960     {MQTT_PROP_WILL_DELAY_INTERVAL, MQTT_PROP_TYPE_INT},
2961     {MQTT_PROP_REQUEST_RESPONSE_INFORMATION, MQTT_PROP_TYPE_BYTE},
2962     {MQTT_PROP_RESPONSE_INFORMATION, MQTT_PROP_TYPE_STRING},
2963     {MQTT_PROP_SERVER_REFERENCE, MQTT_PROP_TYPE_STRING},
2964     {MQTT_PROP_REASON_STRING, MQTT_PROP_TYPE_STRING},
2965     {MQTT_PROP_RECEIVE_MAXIMUM, MQTT_PROP_TYPE_SHORT},
2966     {MQTT_PROP_TOPIC_ALIAS_MAXIMUM, MQTT_PROP_TYPE_SHORT},
2967     {MQTT_PROP_TOPIC_ALIAS, MQTT_PROP_TYPE_SHORT},
2968     {MQTT_PROP_MAXIMUM_QOS, MQTT_PROP_TYPE_BYTE},
2969     {MQTT_PROP_RETAIN_AVAILABLE, MQTT_PROP_TYPE_BYTE},
2970     {MQTT_PROP_USER_PROPERTY, MQTT_PROP_TYPE_STRING_PAIR},
2971     {MQTT_PROP_MAXIMUM_PACKET_SIZE, MQTT_PROP_TYPE_INT},
2972     {MQTT_PROP_WILDCARD_SUBSCRIPTION_AVAILABLE, MQTT_PROP_TYPE_BYTE},
2973     {MQTT_PROP_SUBSCRIPTION_IDENTIFIER_AVAILABLE, MQTT_PROP_TYPE_BYTE},
2974     {MQTT_PROP_SHARED_SUBSCRIPTION_AVAILABLE, MQTT_PROP_TYPE_BYTE}};
2975
2976 void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags,
2977                          uint32_t len) {
2978   uint8_t buf[1 + sizeof(len)], *vlen = &buf[1];
2979   buf[0] = (uint8_t) ((cmd << 4) | flags);
2980   do {
2981     *vlen = len % 0x80;
2982     len /= 0x80;
2983     if (len > 0) *vlen |= 0x80;
2984     vlen++;
2985   } while (len > 0 && vlen < &buf[sizeof(buf)]);
2986   mg_send(c, buf, (size_t) (vlen - buf));
2987 }
2988
2989 static void mg_send_u16(struct mg_connection *c, uint16_t value) {
2990   mg_send(c, &value, sizeof(value));
2991 }
2992
2993 static void mg_send_u32(struct mg_connection *c, uint32_t value) {
2994   mg_send(c, &value, sizeof(value));
2995 }
2996
2997 static uint8_t compute_variable_length_size(size_t length) {
2998   uint8_t bytes_needed = 0;
2999   do {
3000     bytes_needed++;
3001     length /= 0x80;
3002   } while (length > 0);
3003   return bytes_needed;
3004 }
3005
3006 static int encode_variable_length(uint8_t *buf, size_t value) {
3007   int len = 0;
3008
3009   do {
3010     uint8_t byte = (uint8_t) (value % 128);
3011     value /= 128;
3012     if (value > 0) byte |= 0x80;
3013     buf[len++] = byte;
3014   } while (value > 0);
3015
3016   return len;
3017 }
3018
3019 static uint32_t decode_variable_length(const char *buf,
3020                                        uint32_t *bytes_consumed) {
3021   uint32_t value = 0, multiplier = 1, offset;
3022
3023   for (offset = 0; offset < 4; offset++) {
3024     uint8_t encoded_byte = ((uint8_t *) buf)[offset];
3025     value += (encoded_byte & 0x7F) * multiplier;
3026     multiplier *= 128;
3027
3028     if (!(encoded_byte & 0x80)) break;
3029   }
3030
3031   if (bytes_consumed != NULL) *bytes_consumed = offset + 1;
3032
3033   return value;
3034 }
3035
3036 static int mqtt_prop_type_by_id(uint8_t prop_id) {
3037   size_t i, num_properties = sizeof(s_prop_map) / sizeof(s_prop_map[0]);
3038   for (i = 0; i < num_properties; ++i) {
3039     if (s_prop_map[i].id == prop_id) return s_prop_map[i].type;
3040   }
3041   return -1;  // Property ID not found
3042 }
3043
3044 // Returns the size of the properties section, without the
3045 // size of the content's length
3046 static size_t get_properties_length(struct mg_mqtt_prop *props, size_t count) {
3047   size_t i, size = 0;
3048   for (i = 0; i < count; i++) {
3049     size++;  // identifier
3050     switch (mqtt_prop_type_by_id(props[i].id)) {
3051       case MQTT_PROP_TYPE_STRING_PAIR:
3052         size += (uint32_t) (props[i].val.len + props[i].key.len +
3053                             2 * sizeof(uint16_t));
3054         break;
3055       case MQTT_PROP_TYPE_STRING:
3056         size += (uint32_t) (props[i].val.len + sizeof(uint16_t));
3057         break;
3058       case MQTT_PROP_TYPE_BINARY_DATA:
3059         size += (uint32_t) (props[i].val.len + sizeof(uint16_t));
3060         break;
3061       case MQTT_PROP_TYPE_VARIABLE_INT:
3062         size += compute_variable_length_size((uint32_t) props[i].iv);
3063         break;
3064       case MQTT_PROP_TYPE_INT: size += (uint32_t) sizeof(uint32_t); break;
3065       case MQTT_PROP_TYPE_SHORT: size += (uint32_t) sizeof(uint16_t); break;
3066       default: return size;  // cannot parse further down
3067     }
3068   }
3069
3070   return size;
3071 }
3072
3073 // returns the entire size of the properties section, including the
3074 // size of the variable length of the content
3075 static size_t get_props_size(struct mg_mqtt_prop *props, size_t count) {
3076   size_t size = get_properties_length(props, count);
3077   size += compute_variable_length_size(size);
3078   return size;
3079 }
3080
3081 static void mg_send_mqtt_properties(struct mg_connection *c,
3082                                     struct mg_mqtt_prop *props, size_t nprops) {
3083   size_t total_size = get_properties_length(props, nprops);
3084   uint8_t buf_v[4] = {0, 0, 0, 0};
3085   uint8_t buf[4] = {0, 0, 0, 0};
3086   int i, len = encode_variable_length(buf, total_size);
3087
3088   mg_send(c, buf, (size_t) len);
3089   for (i = 0; i < (int) nprops; i++) {
3090     mg_send(c, &props[i].id, sizeof(props[i].id));
3091     switch (mqtt_prop_type_by_id(props[i].id)) {
3092       case MQTT_PROP_TYPE_STRING_PAIR:
3093         mg_send_u16(c, mg_htons((uint16_t) props[i].key.len));
3094         mg_send(c, props[i].key.ptr, props[i].key.len);
3095         mg_send_u16(c, mg_htons((uint16_t) props[i].val.len));
3096         mg_send(c, props[i].val.ptr, props[i].val.len);
3097         break;
3098       case MQTT_PROP_TYPE_BYTE:
3099         mg_send(c, &props[i].iv, sizeof(uint8_t));
3100         break;
3101       case MQTT_PROP_TYPE_SHORT:
3102         mg_send_u16(c, mg_htons((uint16_t) props[i].iv));
3103         break;
3104       case MQTT_PROP_TYPE_INT:
3105         mg_send_u32(c, mg_htonl((uint32_t) props[i].iv));
3106         break;
3107       case MQTT_PROP_TYPE_STRING:
3108         mg_send_u16(c, mg_htons((uint16_t) props[i].val.len));
3109         mg_send(c, props[i].val.ptr, props[i].val.len);
3110         break;
3111       case MQTT_PROP_TYPE_BINARY_DATA:
3112         mg_send_u16(c, mg_htons((uint16_t) props[i].val.len));
3113         mg_send(c, props[i].val.ptr, props[i].val.len);
3114         break;
3115       case MQTT_PROP_TYPE_VARIABLE_INT:
3116         len = encode_variable_length(buf_v, props[i].iv);
3117         mg_send(c, buf_v, (size_t) len);
3118         break;
3119     }
3120   }
3121 }
3122
3123 size_t mg_mqtt_next_prop(struct mg_mqtt_message *msg, struct mg_mqtt_prop *prop,
3124                          size_t ofs) {
3125   uint8_t *i = (uint8_t *) msg->dgram.ptr + msg->props_start + ofs;
3126   size_t new_pos = ofs;
3127   uint32_t bytes_consumed;
3128   prop->id = i[0];
3129
3130   if (ofs >= msg->dgram.len || ofs >= msg->props_start + msg->props_size)
3131     return 0;
3132   i++, new_pos++;
3133
3134   switch (mqtt_prop_type_by_id(prop->id)) {
3135     case MQTT_PROP_TYPE_STRING_PAIR:
3136       prop->key.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
3137       prop->key.ptr = (char *) i + 2;
3138       i += 2 + prop->key.len;
3139       prop->val.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
3140       prop->val.ptr = (char *) i + 2;
3141       new_pos += 2 * sizeof(uint16_t) + prop->val.len + prop->key.len;
3142       break;
3143     case MQTT_PROP_TYPE_BYTE:
3144       prop->iv = (uint8_t) i[0];
3145       new_pos++;
3146       break;
3147     case MQTT_PROP_TYPE_SHORT:
3148       prop->iv = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
3149       new_pos += sizeof(uint16_t);
3150       break;
3151     case MQTT_PROP_TYPE_INT:
3152       prop->iv = ((uint32_t) i[0] << 24) | ((uint32_t) i[1] << 16) |
3153                  ((uint32_t) i[2] << 8) | i[3];
3154       new_pos += sizeof(uint32_t);
3155       break;
3156     case MQTT_PROP_TYPE_STRING:
3157       prop->val.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
3158       prop->val.ptr = (char *) i + 2;
3159       new_pos += 2 + prop->val.len;
3160       break;
3161     case MQTT_PROP_TYPE_BINARY_DATA:
3162       prop->val.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
3163       prop->val.ptr = (char *) i + 2;
3164       new_pos += 2 + prop->val.len;
3165       break;
3166     case MQTT_PROP_TYPE_VARIABLE_INT:
3167       prop->iv = decode_variable_length((char *) i, &bytes_consumed);
3168       new_pos += bytes_consumed;
3169       break;
3170     default: new_pos = 0;
3171   }
3172
3173   return new_pos;
3174 }
3175
3176 void mg_mqtt_login(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
3177   char rnd[10], client_id[21];
3178   struct mg_str cid = opts->client_id;
3179   size_t total_len = 7 + 1 + 2 + 2;
3180   uint8_t hdr[8] = {0, 4, 'M', 'Q', 'T', 'T', opts->version, 0};
3181
3182   if (cid.len == 0) {
3183     mg_random(rnd, sizeof(rnd));
3184     mg_hex(rnd, sizeof(rnd), client_id);
3185     client_id[sizeof(client_id) - 1] = '\0';
3186     cid = mg_str(client_id);
3187   }
3188
3189   if (hdr[6] == 0) hdr[6] = 4;  // If version is not set, use 4 (3.1.1)
3190   c->is_mqtt5 = hdr[6] == 5;    // Set version 5 flag
3191   hdr[7] = (uint8_t) ((opts->qos & 3) << 3);  // Connection flags
3192   if (opts->user.len > 0) {
3193     total_len += 2 + (uint32_t) opts->user.len;
3194     hdr[7] |= MQTT_HAS_USER_NAME;
3195   }
3196   if (opts->pass.len > 0) {
3197     total_len += 2 + (uint32_t) opts->pass.len;
3198     hdr[7] |= MQTT_HAS_PASSWORD;
3199   }
3200   if (opts->topic.len > 0 && opts->message.len > 0) {
3201     total_len += 4 + (uint32_t) opts->topic.len + (uint32_t) opts->message.len;
3202     hdr[7] |= MQTT_HAS_WILL;
3203   }
3204   if (opts->clean || cid.len == 0) hdr[7] |= MQTT_CLEAN_SESSION;
3205   if (opts->retain) hdr[7] |= MQTT_WILL_RETAIN;
3206   total_len += (uint32_t) cid.len;
3207   if (c->is_mqtt5) {
3208     total_len += get_props_size(opts->props, opts->num_props);
3209     if (hdr[7] & MQTT_HAS_WILL)
3210       total_len += get_props_size(opts->will_props, opts->num_will_props);
3211   }
3212
3213   mg_mqtt_send_header(c, MQTT_CMD_CONNECT, 0, (uint32_t) total_len);
3214   mg_send(c, hdr, sizeof(hdr));
3215   // keepalive == 0 means "do not disconnect us!"
3216   mg_send_u16(c, mg_htons((uint16_t) opts->keepalive));
3217
3218   if (c->is_mqtt5) mg_send_mqtt_properties(c, opts->props, opts->num_props);
3219
3220   mg_send_u16(c, mg_htons((uint16_t) cid.len));
3221   mg_send(c, cid.ptr, cid.len);
3222
3223   if (hdr[7] & MQTT_HAS_WILL) {
3224     if (c->is_mqtt5)
3225       mg_send_mqtt_properties(c, opts->will_props, opts->num_will_props);
3226
3227     mg_send_u16(c, mg_htons((uint16_t) opts->topic.len));
3228     mg_send(c, opts->topic.ptr, opts->topic.len);
3229     mg_send_u16(c, mg_htons((uint16_t) opts->message.len));
3230     mg_send(c, opts->message.ptr, opts->message.len);
3231   }
3232   if (opts->user.len > 0) {
3233     mg_send_u16(c, mg_htons((uint16_t) opts->user.len));
3234     mg_send(c, opts->user.ptr, opts->user.len);
3235   }
3236   if (opts->pass.len > 0) {
3237     mg_send_u16(c, mg_htons((uint16_t) opts->pass.len));
3238     mg_send(c, opts->pass.ptr, opts->pass.len);
3239   }
3240 }
3241
3242 void mg_mqtt_pub(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
3243   uint8_t flags = (uint8_t) (((opts->qos & 3) << 1) | (opts->retain ? 1 : 0));
3244   size_t len = 2 + opts->topic.len + opts->message.len;
3245   MG_DEBUG(("%lu [%.*s] -> [%.*s]", c->id, (int) opts->topic.len,
3246             (char *) opts->topic.ptr, (int) opts->message.len,
3247             (char *) opts->message.ptr));
3248   if (opts->qos > 0) len += 2;
3249   if (c->is_mqtt5) len += get_props_size(opts->props, opts->num_props);
3250
3251   mg_mqtt_send_header(c, MQTT_CMD_PUBLISH, flags, (uint32_t) len);
3252   mg_send_u16(c, mg_htons((uint16_t) opts->topic.len));
3253   mg_send(c, opts->topic.ptr, opts->topic.len);
3254   if (opts->qos > 0) {
3255     if (++c->mgr->mqtt_id == 0) ++c->mgr->mqtt_id;
3256     mg_send_u16(c, mg_htons(c->mgr->mqtt_id));
3257   }
3258
3259   if (c->is_mqtt5) mg_send_mqtt_properties(c, opts->props, opts->num_props);
3260
3261   mg_send(c, opts->message.ptr, opts->message.len);
3262 }
3263
3264 void mg_mqtt_sub(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
3265   uint8_t qos_ = opts->qos & 3;
3266   size_t plen = c->is_mqtt5 ? get_props_size(opts->props, opts->num_props) : 0;
3267   size_t len = 2 + opts->topic.len + 2 + 1 + plen;
3268
3269   mg_mqtt_send_header(c, MQTT_CMD_SUBSCRIBE, 2, (uint32_t) len);
3270   if (++c->mgr->mqtt_id == 0) ++c->mgr->mqtt_id;
3271   mg_send_u16(c, mg_htons(c->mgr->mqtt_id));
3272   if (c->is_mqtt5) mg_send_mqtt_properties(c, opts->props, opts->num_props);
3273
3274   mg_send_u16(c, mg_htons((uint16_t) opts->topic.len));
3275   mg_send(c, opts->topic.ptr, opts->topic.len);
3276   mg_send(c, &qos_, sizeof(qos_));
3277 }
3278
3279 int mg_mqtt_parse(const uint8_t *buf, size_t len, uint8_t version,
3280                   struct mg_mqtt_message *m) {
3281   uint8_t lc = 0, *p, *end;
3282   uint32_t n = 0, len_len = 0;
3283
3284   memset(m, 0, sizeof(*m));
3285   m->dgram.ptr = (char *) buf;
3286   if (len < 2) return MQTT_INCOMPLETE;
3287   m->cmd = (uint8_t) (buf[0] >> 4);
3288   m->qos = (buf[0] >> 1) & 3;
3289
3290   n = len_len = 0;
3291   p = (uint8_t *) buf + 1;
3292   while ((size_t) (p - buf) < len) {
3293     lc = *((uint8_t *) p++);
3294     n += (uint32_t) ((lc & 0x7f) << 7 * len_len);
3295     len_len++;
3296     if (!(lc & 0x80)) break;
3297     if (len_len >= 4) return MQTT_MALFORMED;
3298   }
3299   end = p + n;
3300   if ((lc & 0x80) || (end > buf + len)) return MQTT_INCOMPLETE;
3301   m->dgram.len = (size_t) (end - buf);
3302
3303   switch (m->cmd) {
3304     case MQTT_CMD_CONNACK:
3305       if (end - p < 2) return MQTT_MALFORMED;
3306       m->ack = p[1];
3307       break;
3308     case MQTT_CMD_PUBACK:
3309     case MQTT_CMD_PUBREC:
3310     case MQTT_CMD_PUBREL:
3311     case MQTT_CMD_PUBCOMP:
3312     case MQTT_CMD_SUBSCRIBE:
3313     case MQTT_CMD_SUBACK:
3314     case MQTT_CMD_UNSUBSCRIBE:
3315     case MQTT_CMD_UNSUBACK:
3316       if (p + 2 > end) return MQTT_MALFORMED;
3317       m->id = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
3318       p += 2;
3319       break;
3320     case MQTT_CMD_PUBLISH: {
3321       if (p + 2 > end) return MQTT_MALFORMED;
3322       m->topic.len = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
3323       m->topic.ptr = (char *) p + 2;
3324       p += 2 + m->topic.len;
3325       if (p > end) return MQTT_MALFORMED;
3326       if (m->qos > 0) {
3327         if (p + 2 > end) return MQTT_MALFORMED;
3328         m->id = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
3329         p += 2;
3330       }
3331       if (p > end) return MQTT_MALFORMED;
3332       if (version == 5 && p + 2 < end) {
3333         m->props_size = decode_variable_length((char *) p, &len_len);
3334         m->props_start = (size_t) (p + len_len - buf);
3335         p += len_len + m->props_size;
3336       }
3337       if (p > end) return MQTT_MALFORMED;
3338       m->data.ptr = (char *) p;
3339       m->data.len = (size_t) (end - p);
3340       break;
3341     }
3342     default: break;
3343   }
3344   return MQTT_OK;
3345 }
3346
3347 static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data,
3348                     void *fn_data) {
3349   if (ev == MG_EV_READ) {
3350     for (;;) {
3351       uint8_t version = c->is_mqtt5 ? 5 : 4;
3352       struct mg_mqtt_message mm;
3353       int rc = mg_mqtt_parse(c->recv.buf, c->recv.len, version, &mm);
3354       if (rc == MQTT_MALFORMED) {
3355         MG_ERROR(("%lu MQTT malformed message", c->id));
3356         c->is_closing = 1;
3357         break;
3358       } else if (rc == MQTT_OK) {
3359         MG_VERBOSE(("%lu MQTT CMD %d len %d [%.*s]", c->id, mm.cmd,
3360                     (int) mm.dgram.len, (int) mm.data.len, mm.data.ptr));
3361         switch (mm.cmd) {
3362           case MQTT_CMD_CONNACK:
3363             mg_call(c, MG_EV_MQTT_OPEN, &mm.ack);
3364             if (mm.ack == 0) {
3365               MG_DEBUG(("%lu Connected", c->id));
3366             } else {
3367               MG_ERROR(("%lu MQTT auth failed, code %d", c->id, mm.ack));
3368               c->is_closing = 1;
3369             }
3370             break;
3371           case MQTT_CMD_PUBLISH: {
3372             MG_DEBUG(("%lu [%.*s] -> [%.*s]", c->id, (int) mm.topic.len,
3373                       mm.topic.ptr, (int) mm.data.len, mm.data.ptr));
3374             if (mm.qos > 0) {
3375               uint16_t id = mg_htons(mm.id);
3376               uint32_t remaining_len = sizeof(id);
3377               if (c->is_mqtt5) remaining_len += 1;
3378
3379               mg_mqtt_send_header(c, MQTT_CMD_PUBACK, 0, remaining_len);
3380               mg_send(c, &id, sizeof(id));
3381
3382               if (c->is_mqtt5) {
3383                 uint16_t zero = 0;
3384                 mg_send(c, &zero, sizeof(zero));
3385               }
3386             }
3387             mg_call(c, MG_EV_MQTT_MSG, &mm);
3388             break;
3389           }
3390         }
3391         mg_call(c, MG_EV_MQTT_CMD, &mm);
3392         mg_iobuf_del(&c->recv, 0, mm.dgram.len);
3393       } else {
3394         break;
3395       }
3396     }
3397   }
3398   (void) ev_data;
3399   (void) fn_data;
3400 }
3401
3402 void mg_mqtt_ping(struct mg_connection *nc) {
3403   mg_mqtt_send_header(nc, MQTT_CMD_PINGREQ, 0, 0);
3404 }
3405
3406 void mg_mqtt_pong(struct mg_connection *nc) {
3407   mg_mqtt_send_header(nc, MQTT_CMD_PINGRESP, 0, 0);
3408 }
3409
3410 void mg_mqtt_disconnect(struct mg_connection *c,
3411                         const struct mg_mqtt_opts *opts) {
3412   size_t len = 0;
3413   if (c->is_mqtt5) len = 1 + get_props_size(opts->props, opts->num_props);
3414   mg_mqtt_send_header(c, MQTT_CMD_DISCONNECT, 0, (uint32_t) len);
3415
3416   if (c->is_mqtt5) {
3417     uint8_t zero = 0;
3418     mg_send(c, &zero, sizeof(zero));  // reason code
3419     mg_send_mqtt_properties(c, opts->props, opts->num_props);
3420   }
3421 }
3422
3423 struct mg_connection *mg_mqtt_connect(struct mg_mgr *mgr, const char *url,
3424                                       const struct mg_mqtt_opts *opts,
3425                                       mg_event_handler_t fn, void *fn_data) {
3426   struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
3427   if (c != NULL) {
3428     struct mg_mqtt_opts empty;
3429     memset(&empty, 0, sizeof(empty));
3430     mg_mqtt_login(c, opts == NULL ? &empty : opts);
3431     c->pfn = mqtt_cb;
3432   }
3433   return c;
3434 }
3435
3436 struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
3437                                      mg_event_handler_t fn, void *fn_data) {
3438   struct mg_connection *c = mg_listen(mgr, url, fn, fn_data);
3439   if (c != NULL) c->pfn = mqtt_cb, c->pfn_data = mgr;
3440   return c;
3441 }
3442
3443 #ifdef MG_ENABLE_LINES
3444 #line 1 "src/net.c"
3445 #endif
3446
3447
3448
3449
3450
3451
3452
3453
3454 size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list *ap) {
3455   size_t old = c->send.len;
3456   mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
3457   return c->send.len - old;
3458 }
3459
3460 size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
3461   size_t len = 0;
3462   va_list ap;
3463   va_start(ap, fmt);
3464   len = mg_vprintf(c, fmt, &ap);
3465   va_end(ap);
3466   return len;
3467 }
3468
3469 static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
3470   if (mg_vcasecmp(&str, "localhost") != 0) return false;
3471   addr->ip = mg_htonl(0x7f000001);
3472   addr->is_ip6 = false;
3473   return true;
3474 }
3475
3476 static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
3477   if (str.len > 0) return false;
3478   addr->ip = 0;
3479   addr->is_ip6 = false;
3480   return true;
3481 }
3482
3483 static bool mg_aton4(struct mg_str str, struct mg_addr *addr) {
3484   uint8_t data[4] = {0, 0, 0, 0};
3485   size_t i, num_dots = 0;
3486   for (i = 0; i < str.len; i++) {
3487     if (str.ptr[i] >= '0' && str.ptr[i] <= '9') {
3488       int octet = data[num_dots] * 10 + (str.ptr[i] - '0');
3489       if (octet > 255) return false;
3490       data[num_dots] = (uint8_t) octet;
3491     } else if (str.ptr[i] == '.') {
3492       if (num_dots >= 3 || i == 0 || str.ptr[i - 1] == '.') return false;
3493       num_dots++;
3494     } else {
3495       return false;
3496     }
3497   }
3498   if (num_dots != 3 || str.ptr[i - 1] == '.') return false;
3499   memcpy(&addr->ip, data, sizeof(data));
3500   addr->is_ip6 = false;
3501   return true;
3502 }
3503
3504 static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) {
3505   int i;
3506   if (str.len < 14) return false;
3507   if (str.ptr[0] != ':' || str.ptr[1] != ':' || str.ptr[6] != ':') return false;
3508   for (i = 2; i < 6; i++) {
3509     if (str.ptr[i] != 'f' && str.ptr[i] != 'F') return false;
3510   }
3511   if (!mg_aton4(mg_str_n(&str.ptr[7], str.len - 7), addr)) return false;
3512   memset(addr->ip6, 0, sizeof(addr->ip6));
3513   addr->ip6[10] = addr->ip6[11] = 255;
3514   memcpy(&addr->ip6[12], &addr->ip, 4);
3515   addr->is_ip6 = true;
3516   return true;
3517 }
3518
3519 static bool mg_aton6(struct mg_str str, struct mg_addr *addr) {
3520   size_t i, j = 0, n = 0, dc = 42;
3521   if (str.len > 2 && str.ptr[0] == '[') str.ptr++, str.len -= 2;
3522   if (mg_v4mapped(str, addr)) return true;
3523   for (i = 0; i < str.len; i++) {
3524     if ((str.ptr[i] >= '0' && str.ptr[i] <= '9') ||
3525         (str.ptr[i] >= 'a' && str.ptr[i] <= 'f') ||
3526         (str.ptr[i] >= 'A' && str.ptr[i] <= 'F')) {
3527       unsigned long val;
3528       if (i > j + 3) return false;
3529       // MG_DEBUG(("%zu %zu [%.*s]", i, j, (int) (i - j + 1), &str.ptr[j]));
3530       val = mg_unhexn(&str.ptr[j], i - j + 1);
3531       addr->ip6[n] = (uint8_t) ((val >> 8) & 255);
3532       addr->ip6[n + 1] = (uint8_t) (val & 255);
3533     } else if (str.ptr[i] == ':') {
3534       j = i + 1;
3535       if (i > 0 && str.ptr[i - 1] == ':') {
3536         dc = n;  // Double colon
3537         if (i > 1 && str.ptr[i - 2] == ':') return false;
3538       } else if (i > 0) {
3539         n += 2;
3540       }
3541       if (n > 14) return false;
3542       addr->ip6[n] = addr->ip6[n + 1] = 0;  // For trailing ::
3543     } else {
3544       return false;
3545     }
3546   }
3547   if (n < 14 && dc == 42) return false;
3548   if (n < 14) {
3549     memmove(&addr->ip6[dc + (14 - n)], &addr->ip6[dc], n - dc + 2);
3550     memset(&addr->ip6[dc], 0, 14 - n);
3551   }
3552   addr->is_ip6 = true;
3553   return true;
3554 }
3555
3556 bool mg_aton(struct mg_str str, struct mg_addr *addr) {
3557   // MG_INFO(("[%.*s]", (int) str.len, str.ptr));
3558   return mg_atone(str, addr) || mg_atonl(str, addr) || mg_aton4(str, addr) ||
3559          mg_aton6(str, addr);
3560 }
3561
3562 struct mg_connection *mg_alloc_conn(struct mg_mgr *mgr) {
3563   struct mg_connection *c =
3564       (struct mg_connection *) calloc(1, sizeof(*c) + mgr->extraconnsize);
3565   if (c != NULL) {
3566     c->mgr = mgr;
3567     c->send.align = c->recv.align = MG_IO_SIZE;
3568     c->id = ++mgr->nextid;
3569   }
3570   return c;
3571 }
3572
3573 void mg_close_conn(struct mg_connection *c) {
3574   mg_resolve_cancel(c);  // Close any pending DNS query
3575   LIST_DELETE(struct mg_connection, &c->mgr->conns, c);
3576   if (c == c->mgr->dns4.c) c->mgr->dns4.c = NULL;
3577   if (c == c->mgr->dns6.c) c->mgr->dns6.c = NULL;
3578   // Order of operations is important. `MG_EV_CLOSE` event must be fired
3579   // before we deallocate received data, see #1331
3580   mg_call(c, MG_EV_CLOSE, NULL);
3581   MG_DEBUG(("%lu %p closed", c->id, c->fd));
3582
3583   mg_tls_free(c);
3584   mg_iobuf_free(&c->recv);
3585   mg_iobuf_free(&c->send);
3586   memset(c, 0, sizeof(*c));
3587   free(c);
3588 }
3589
3590 struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
3591                                  mg_event_handler_t fn, void *fn_data) {
3592   struct mg_connection *c = NULL;
3593   if (url == NULL || url[0] == '\0') {
3594     MG_ERROR(("null url"));
3595   } else if ((c = mg_alloc_conn(mgr)) == NULL) {
3596     MG_ERROR(("OOM"));
3597   } else {
3598     LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
3599     c->is_udp = (strncmp(url, "udp:", 4) == 0);
3600     c->fd = (void *) (size_t) MG_INVALID_SOCKET;
3601     c->fn = fn;
3602     c->is_client = true;
3603     c->fn_data = fn_data;
3604     MG_DEBUG(("%lu %p %s", c->id, c->fd, url));
3605     mg_call(c, MG_EV_OPEN, NULL);
3606     mg_resolve(c, url);
3607   }
3608   return c;
3609 }
3610
3611 struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
3612                                 mg_event_handler_t fn, void *fn_data) {
3613   struct mg_connection *c = NULL;
3614   if ((c = mg_alloc_conn(mgr)) == NULL) {
3615     MG_ERROR(("OOM %s", url));
3616   } else if (!mg_open_listener(c, url)) {
3617     MG_ERROR(("Failed: %s, errno %d", url, errno));
3618     free(c);
3619     c = NULL;
3620   } else {
3621     c->is_listening = 1;
3622     c->is_udp = strncmp(url, "udp:", 4) == 0;
3623     LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
3624     c->fn = fn;
3625     c->fn_data = fn_data;
3626     mg_call(c, MG_EV_OPEN, NULL);
3627     MG_DEBUG(("%lu %p %s", c->id, c->fd, url));
3628   }
3629   return c;
3630 }
3631
3632 struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd,
3633                                 mg_event_handler_t fn, void *fn_data) {
3634   struct mg_connection *c = mg_alloc_conn(mgr);
3635   if (c != NULL) {
3636     c->fd = (void *) (size_t) fd;
3637     c->fn = fn;
3638     c->fn_data = fn_data;
3639     MG_EPOLL_ADD(c);
3640     mg_call(c, MG_EV_OPEN, NULL);
3641     LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
3642   }
3643   return c;
3644 }
3645
3646 struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
3647                               unsigned flags, void (*fn)(void *), void *arg) {
3648   struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t));
3649   if (t != NULL) {
3650     mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg);
3651     t->id = mgr->timerid++;
3652   }
3653   return t;
3654 }
3655
3656 void mg_mgr_free(struct mg_mgr *mgr) {
3657   struct mg_connection *c;
3658   struct mg_timer *tmp, *t = mgr->timers;
3659   while (t != NULL) tmp = t->next, free(t), t = tmp;
3660   mgr->timers = NULL;  // Important. Next call to poll won't touch timers
3661   for (c = mgr->conns; c != NULL; c = c->next) c->is_closing = 1;
3662   mg_mgr_poll(mgr, 0);
3663 #if MG_ENABLE_FREERTOS_TCP
3664   FreeRTOS_DeleteSocketSet(mgr->ss);
3665 #endif
3666   MG_DEBUG(("All connections closed"));
3667 #if MG_ENABLE_EPOLL
3668   if (mgr->epoll_fd >= 0) close(mgr->epoll_fd), mgr->epoll_fd = -1;
3669 #endif
3670 }
3671
3672 void mg_mgr_init(struct mg_mgr *mgr) {
3673   memset(mgr, 0, sizeof(*mgr));
3674 #if MG_ENABLE_EPOLL
3675   if ((mgr->epoll_fd = epoll_create1(0)) < 0) MG_ERROR(("epoll: %d", errno));
3676 #else
3677   mgr->epoll_fd = -1;
3678 #endif
3679 #if MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK
3680   // clang-format off
3681   { WSADATA data; WSAStartup(MAKEWORD(2, 2), &data); }
3682   // clang-format on
3683 #elif MG_ENABLE_FREERTOS_TCP
3684   mgr->ss = FreeRTOS_CreateSocketSet();
3685 #elif defined(__unix) || defined(__unix__) || defined(__APPLE__)
3686   // Ignore SIGPIPE signal, so if client cancels the request, it
3687   // won't kill the whole process.
3688   signal(SIGPIPE, SIG_IGN);
3689 #endif
3690   mgr->dnstimeout = 3000;
3691   mgr->dns4.url = "udp://8.8.8.8:53";
3692   mgr->dns6.url = "udp://[2001:4860:4860::8888]:53";
3693 }
3694
3695 #ifdef MG_ENABLE_LINES
3696 #line 1 "src/printf.c"
3697 #endif
3698
3699
3700
3701
3702 size_t mg_queue_vprintf(struct mg_queue *q, const char *fmt, va_list *ap) {
3703   size_t len = mg_snprintf(NULL, 0, fmt, ap);
3704   char *buf;
3705   if (len == 0 || mg_queue_book(q, &buf, len + 1) < len + 1) {
3706     len = 0;  // Nah. Not enough space
3707   } else {
3708     len = mg_vsnprintf((char *) buf, len + 1, fmt, ap);
3709     mg_queue_add(q, len);
3710   }
3711   return len;
3712 }
3713
3714 size_t mg_queue_printf(struct mg_queue *q, const char *fmt, ...) {
3715   va_list ap;
3716   size_t len;
3717   va_start(ap, fmt);
3718   len = mg_queue_vprintf(q, fmt, &ap);
3719   va_end(ap);
3720   return len;
3721 }
3722
3723 static void mg_pfn_iobuf_private(char ch, void *param, bool expand) {
3724   struct mg_iobuf *io = (struct mg_iobuf *) param;
3725   if (expand && io->len + 2 > io->size) mg_iobuf_resize(io, io->len + 2);
3726   if (io->len + 2 <= io->size) {
3727     io->buf[io->len++] = (uint8_t) ch;
3728     io->buf[io->len] = 0;
3729   } else if (io->len < io->size) {
3730     io->buf[io->len++] = 0;  // Guarantee to 0-terminate
3731   }
3732 }
3733
3734 static void mg_putchar_iobuf_static(char ch, void *param) {
3735   mg_pfn_iobuf_private(ch, param, false);
3736 }
3737
3738 void mg_pfn_iobuf(char ch, void *param) {
3739   mg_pfn_iobuf_private(ch, param, true);
3740 }
3741
3742 size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap) {
3743   struct mg_iobuf io = {(uint8_t *) buf, len, 0, 0};
3744   size_t n = mg_vxprintf(mg_putchar_iobuf_static, &io, fmt, ap);
3745   if (n < len) buf[n] = '\0';
3746   return n;
3747 }
3748
3749 size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...) {
3750   va_list ap;
3751   size_t n;
3752   va_start(ap, fmt);
3753   n = mg_vsnprintf(buf, len, fmt, &ap);
3754   va_end(ap);
3755   return n;
3756 }
3757
3758 char *mg_vmprintf(const char *fmt, va_list *ap) {
3759   struct mg_iobuf io = {0, 0, 0, 256};
3760   mg_vxprintf(mg_pfn_iobuf, &io, fmt, ap);
3761   return (char *) io.buf;
3762 }
3763
3764 char *mg_mprintf(const char *fmt, ...) {
3765   char *s;
3766   va_list ap;
3767   va_start(ap, fmt);
3768   s = mg_vmprintf(fmt, &ap);
3769   va_end(ap);
3770   return s;
3771 }
3772
3773 void mg_pfn_stdout(char c, void *param) {
3774   putchar(c);
3775   (void) param;
3776 }
3777
3778 static size_t print_ip4(void (*out)(char, void *), void *arg, uint8_t *p) {
3779   return mg_xprintf(out, arg, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
3780 }
3781
3782 static size_t print_ip6(void (*out)(char, void *), void *arg, uint16_t *p) {
3783   return mg_xprintf(out, arg, "[%x:%x:%x:%x:%x:%x:%x:%x]", mg_ntohs(p[0]),
3784                     mg_ntohs(p[1]), mg_ntohs(p[2]), mg_ntohs(p[3]),
3785                     mg_ntohs(p[4]), mg_ntohs(p[5]), mg_ntohs(p[6]),
3786                     mg_ntohs(p[7]));
3787 }
3788
3789 size_t mg_print_ip4(void (*out)(char, void *), void *arg, va_list *ap) {
3790   uint8_t *p = va_arg(*ap, uint8_t *);
3791   return print_ip4(out, arg, p);
3792 }
3793
3794 size_t mg_print_ip6(void (*out)(char, void *), void *arg, va_list *ap) {
3795   uint16_t *p = va_arg(*ap, uint16_t *);
3796   return print_ip6(out, arg, p);
3797 }
3798
3799 size_t mg_print_ip(void (*out)(char, void *), void *arg, va_list *ap) {
3800   struct mg_addr *addr = va_arg(*ap, struct mg_addr *);
3801   if (addr->is_ip6) return print_ip6(out, arg, (uint16_t *) addr->ip6);
3802   return print_ip4(out, arg, (uint8_t *) &addr->ip);
3803 }
3804
3805 size_t mg_print_ip_port(void (*out)(char, void *), void *arg, va_list *ap) {
3806   struct mg_addr *a = va_arg(*ap, struct mg_addr *);
3807   return mg_xprintf(out, arg, "%M:%hu", mg_print_ip, a, mg_ntohs(a->port));
3808 }
3809
3810 size_t mg_print_mac(void (*out)(char, void *), void *arg, va_list *ap) {
3811   uint8_t *p = va_arg(*ap, uint8_t *);
3812   return mg_xprintf(out, arg, "%02x:%02x:%02x:%02x:%02x:%02x", p[0], p[1], p[2],
3813                     p[3], p[4], p[5]);
3814 }
3815
3816 static char mg_esc(int c, bool esc) {
3817   const char *p, *esc1 = "\b\f\n\r\t\\\"", *esc2 = "bfnrt\\\"";
3818   for (p = esc ? esc1 : esc2; *p != '\0'; p++) {
3819     if (*p == c) return esc ? esc2[p - esc1] : esc1[p - esc2];
3820   }
3821   return 0;
3822 }
3823
3824 static char mg_escape(int c) {
3825   return mg_esc(c, true);
3826 }
3827
3828 static size_t qcpy(void (*out)(char, void *), void *ptr, char *buf,
3829                    size_t len) {
3830   size_t i = 0, extra = 0;
3831   for (i = 0; i < len && buf[i] != '\0'; i++) {
3832     char c = mg_escape(buf[i]);
3833     if (c) {
3834       out('\\', ptr), out(c, ptr), extra++;
3835     } else {
3836       out(buf[i], ptr);
3837     }
3838   }
3839   return i + extra;
3840 }
3841
3842 static size_t bcpy(void (*out)(char, void *), void *arg, uint8_t *buf,
3843                    size_t len) {
3844   size_t i, j, n = 0;
3845   const char *t =
3846       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
3847   for (i = 0; i < len; i += 3) {
3848     uint8_t c1 = buf[i], c2 = i + 1 < len ? buf[i + 1] : 0,
3849             c3 = i + 2 < len ? buf[i + 2] : 0;
3850     char tmp[4] = {t[c1 >> 2], t[(c1 & 3) << 4 | (c2 >> 4)], '=', '='};
3851     if (i + 1 < len) tmp[2] = t[(c2 & 15) << 2 | (c3 >> 6)];
3852     if (i + 2 < len) tmp[3] = t[c3 & 63];
3853     for (j = 0; j < sizeof(tmp) && tmp[j] != '\0'; j++) out(tmp[j], arg);
3854     n += j;
3855   }
3856   return n;
3857 }
3858
3859 size_t mg_print_hex(void (*out)(char, void *), void *arg, va_list *ap) {
3860   size_t bl = (size_t) va_arg(*ap, int);
3861   uint8_t *p = va_arg(*ap, uint8_t *);
3862   const char *hex = "0123456789abcdef";
3863   size_t j;
3864   for (j = 0; j < bl; j++) {
3865     out(hex[(p[j] >> 4) & 0x0F], arg);
3866     out(hex[p[j] & 0x0F], arg);
3867   }
3868   return 2 * bl;
3869 }
3870 size_t mg_print_base64(void (*out)(char, void *), void *arg, va_list *ap) {
3871   size_t len = (size_t) va_arg(*ap, int);
3872   uint8_t *buf = va_arg(*ap, uint8_t *);
3873   return bcpy(out, arg, buf, len);
3874 }
3875
3876 size_t mg_print_esc(void (*out)(char, void *), void *arg, va_list *ap) {
3877   size_t len = (size_t) va_arg(*ap, int);
3878   char *p = va_arg(*ap, char *);
3879   if (len == 0) len = p == NULL ? 0 : strlen(p);
3880   return qcpy(out, arg, p, len);
3881 }
3882
3883 #ifdef MG_ENABLE_LINES
3884 #line 1 "src/queue.c"
3885 #endif
3886
3887
3888
3889 #if defined(__GNUC__) || defined(__clang__)
3890 #define MG_MEMORY_BARRIER() __sync_synchronize()
3891 #elif defined(_MSC_VER) && _MSC_VER >= 1700
3892 #define MG_MEMORY_BARRIER() MemoryBarrier()
3893 #elif !defined(MG_MEMORY_BARRIER)
3894 #define MG_MEMORY_BARRIER()
3895 #endif
3896
3897 // Every message in a queue is prepended by a 32-bit message length (ML).
3898 // If ML is 0, then it is the end, and reader must wrap to the beginning.
3899 //
3900 //  Queue when q->tail <= q->head:
3901 //  |----- free -----| ML | message1 | ML | message2 |  ----- free ------|
3902 //  ^                ^                               ^                   ^
3903 // buf              tail                            head                len
3904 //
3905 //  Queue when q->tail > q->head:
3906 //  | ML | message2 |----- free ------| ML | message1 | 0 |---- free ----|
3907 //  ^               ^                 ^                                  ^
3908 // buf             head              tail                               len
3909
3910 void mg_queue_init(struct mg_queue *q, char *buf, size_t size) {
3911   q->size = size;
3912   q->buf = buf;
3913   q->head = q->tail = 0;
3914 }
3915
3916 static size_t mg_queue_read_len(struct mg_queue *q) {
3917   uint32_t n = 0;
3918   MG_MEMORY_BARRIER();
3919   memcpy(&n, q->buf + q->tail, sizeof(n));
3920   assert(q->tail + n + sizeof(n) <= q->size);
3921   return n;
3922 }
3923
3924 static void mg_queue_write_len(struct mg_queue *q, size_t len) {
3925   uint32_t n = (uint32_t) len;
3926   memcpy(q->buf + q->head, &n, sizeof(n));
3927   MG_MEMORY_BARRIER();
3928 }
3929
3930 size_t mg_queue_book(struct mg_queue *q, char **buf, size_t len) {
3931   size_t space = 0, hs = sizeof(uint32_t) * 2;  // *2 is for the 0 marker
3932   if (q->head >= q->tail && q->head + len + hs <= q->size) {
3933     space = q->size - q->head - hs;  // There is enough space
3934   } else if (q->head >= q->tail && q->tail > hs) {
3935     mg_queue_write_len(q, 0);  // Not enough space ahead
3936     q->head = 0;               // Wrap head to the beginning
3937   }
3938   if (q->head + hs + len < q->tail) space = q->tail - q->head - hs;
3939   if (buf != NULL) *buf = q->buf + q->head + sizeof(uint32_t);
3940   return space;
3941 }
3942
3943 size_t mg_queue_next(struct mg_queue *q, char **buf) {
3944   size_t len = 0;
3945   if (q->tail != q->head) {
3946     len = mg_queue_read_len(q);
3947     if (len == 0) {  // Zero (head wrapped) ?
3948       q->tail = 0;   // Reset tail to the start
3949       if (q->head > q->tail) len = mg_queue_read_len(q);  // Read again
3950     }
3951   }
3952   if (buf != NULL) *buf = q->buf + q->tail + sizeof(uint32_t);
3953   assert(q->tail + len <= q->size);
3954   return len;
3955 }
3956
3957 void mg_queue_add(struct mg_queue *q, size_t len) {
3958   assert(len > 0);
3959   mg_queue_write_len(q, len);
3960   assert(q->head + sizeof(uint32_t) * 2 + len <= q->size);
3961   q->head += len + sizeof(uint32_t);
3962 }
3963
3964 void mg_queue_del(struct mg_queue *q, size_t len) {
3965   q->tail += len + sizeof(uint32_t);
3966   assert(q->tail + sizeof(uint32_t) <= q->size);
3967 }
3968
3969 #ifdef MG_ENABLE_LINES
3970 #line 1 "src/rpc.c"
3971 #endif
3972
3973
3974
3975 void mg_rpc_add(struct mg_rpc **head, struct mg_str method,
3976                 void (*fn)(struct mg_rpc_req *), void *fn_data) {
3977   struct mg_rpc *rpc = (struct mg_rpc *) calloc(1, sizeof(*rpc));
3978   if (rpc != NULL) {
3979     rpc->method = mg_strdup(method), rpc->fn = fn, rpc->fn_data = fn_data;
3980     rpc->next = *head, *head = rpc;
3981   }
3982 }
3983
3984 void mg_rpc_del(struct mg_rpc **head, void (*fn)(struct mg_rpc_req *)) {
3985   struct mg_rpc *r;
3986   while ((r = *head) != NULL) {
3987     if (r->fn == fn || fn == NULL) {
3988       *head = r->next;
3989       free((void *) r->method.ptr);
3990       free(r);
3991     } else {
3992       head = &(*head)->next;
3993     }
3994   }
3995 }
3996
3997 static void mg_rpc_call(struct mg_rpc_req *r, struct mg_str method) {
3998   struct mg_rpc *h = r->head == NULL ? NULL : *r->head;
3999   while (h != NULL && !mg_match(method, h->method, NULL)) h = h->next;
4000   if (h != NULL) {
4001     r->rpc = h;
4002     h->fn(r);
4003   } else {
4004     mg_rpc_err(r, -32601, "\"%.*s not found\"", (int) method.len, method.ptr);
4005   }
4006 }
4007
4008 void mg_rpc_process(struct mg_rpc_req *r) {
4009   int len, off = mg_json_get(r->frame, "$.method", &len);
4010   if (off > 0 && r->frame.ptr[off] == '"') {
4011     struct mg_str method = mg_str_n(&r->frame.ptr[off + 1], (size_t) len - 2);
4012     mg_rpc_call(r, method);
4013   } else if ((off = mg_json_get(r->frame, "$.result", &len)) > 0 ||
4014              (off = mg_json_get(r->frame, "$.error", &len)) > 0) {
4015     mg_rpc_call(r, mg_str(""));  // JSON response! call "" method handler
4016   } else {
4017     mg_rpc_err(r, -32700, "%m", mg_print_esc, (int) r->frame.len,
4018                r->frame.ptr);  // Invalid
4019   }
4020 }
4021
4022 void mg_rpc_vok(struct mg_rpc_req *r, const char *fmt, va_list *ap) {
4023   int len, off = mg_json_get(r->frame, "$.id", &len);
4024   if (off > 0) {
4025     mg_xprintf(r->pfn, r->pfn_data, "{%m:%.*s,%m:", mg_print_esc, 0, "id", len,
4026                &r->frame.ptr[off], mg_print_esc, 0, "result");
4027     mg_vxprintf(r->pfn, r->pfn_data, fmt == NULL ? "null" : fmt, ap);
4028     mg_xprintf(r->pfn, r->pfn_data, "}");
4029   }
4030 }
4031
4032 void mg_rpc_ok(struct mg_rpc_req *r, const char *fmt, ...) {
4033   va_list ap;
4034   va_start(ap, fmt);
4035   mg_rpc_vok(r, fmt, &ap);
4036   va_end(ap);
4037 }
4038
4039 void mg_rpc_verr(struct mg_rpc_req *r, int code, const char *fmt, va_list *ap) {
4040   int len, off = mg_json_get(r->frame, "$.id", &len);
4041   mg_xprintf(r->pfn, r->pfn_data, "{");
4042   if (off > 0) {
4043     mg_xprintf(r->pfn, r->pfn_data, "%m:%.*s,", mg_print_esc, 0, "id", len,
4044                &r->frame.ptr[off]);
4045   }
4046   mg_xprintf(r->pfn, r->pfn_data, "%m:{%m:%d,%m:", mg_print_esc, 0, "error",
4047              mg_print_esc, 0, "code", code, mg_print_esc, 0, "message");
4048   mg_vxprintf(r->pfn, r->pfn_data, fmt == NULL ? "null" : fmt, ap);
4049   mg_xprintf(r->pfn, r->pfn_data, "}}");
4050 }
4051
4052 void mg_rpc_err(struct mg_rpc_req *r, int code, const char *fmt, ...) {
4053   va_list ap;
4054   va_start(ap, fmt);
4055   mg_rpc_verr(r, code, fmt, &ap);
4056   va_end(ap);
4057 }
4058
4059 static size_t print_methods(mg_pfn_t pfn, void *pfn_data, va_list *ap) {
4060   struct mg_rpc *h, **head = (struct mg_rpc **) va_arg(*ap, void **);
4061   size_t len = 0;
4062   for (h = *head; h != NULL; h = h->next) {
4063     if (h->method.len == 0) continue;  // Ignore response handler
4064     len += mg_xprintf(pfn, pfn_data, "%s%m", h == *head ? "" : ",",
4065                       mg_print_esc, (int) h->method.len, h->method.ptr);
4066   }
4067   return len;
4068 }
4069
4070 void mg_rpc_list(struct mg_rpc_req *r) {
4071   mg_rpc_ok(r, "[%M]", print_methods, r->head);
4072 }
4073
4074 #ifdef MG_ENABLE_LINES
4075 #line 1 "src/sha1.c"
4076 #endif
4077 /* Copyright(c) By Steve Reid <steve@edmweb.com> */
4078 /* 100% Public Domain */
4079
4080
4081
4082 union char64long16 {
4083   unsigned char c[64];
4084   uint32_t l[16];
4085 };
4086
4087 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
4088
4089 static uint32_t blk0(union char64long16 *block, int i) {
4090   if (MG_BIG_ENDIAN) {
4091   } else {
4092     block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) |
4093                   (rol(block->l[i], 8) & 0x00FF00FF);
4094   }
4095   return block->l[i];
4096 }
4097
4098 /* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */
4099 #undef blk
4100 #undef R0
4101 #undef R1
4102 #undef R2
4103 #undef R3
4104 #undef R4
4105
4106 #define blk(i)                                                               \
4107   (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
4108                               block->l[(i + 2) & 15] ^ block->l[i & 15],     \
4109                           1))
4110 #define R0(v, w, x, y, z, i)                                          \
4111   z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
4112   w = rol(w, 30);
4113 #define R1(v, w, x, y, z, i)                                  \
4114   z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
4115   w = rol(w, 30);
4116 #define R2(v, w, x, y, z, i)                          \
4117   z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
4118   w = rol(w, 30);
4119 #define R3(v, w, x, y, z, i)                                        \
4120   z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
4121   w = rol(w, 30);
4122 #define R4(v, w, x, y, z, i)                          \
4123   z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
4124   w = rol(w, 30);
4125
4126 static void mg_sha1_transform(uint32_t state[5],
4127                               const unsigned char *buffer) {
4128   uint32_t a, b, c, d, e;
4129   union char64long16 block[1];
4130
4131   memcpy(block, buffer, 64);
4132   a = state[0];
4133   b = state[1];
4134   c = state[2];
4135   d = state[3];
4136   e = state[4];
4137   R0(a, b, c, d, e, 0);
4138   R0(e, a, b, c, d, 1);
4139   R0(d, e, a, b, c, 2);
4140   R0(c, d, e, a, b, 3);
4141   R0(b, c, d, e, a, 4);
4142   R0(a, b, c, d, e, 5);
4143   R0(e, a, b, c, d, 6);
4144   R0(d, e, a, b, c, 7);
4145   R0(c, d, e, a, b, 8);
4146   R0(b, c, d, e, a, 9);
4147   R0(a, b, c, d, e, 10);
4148   R0(e, a, b, c, d, 11);
4149   R0(d, e, a, b, c, 12);
4150   R0(c, d, e, a, b, 13);
4151   R0(b, c, d, e, a, 14);
4152   R0(a, b, c, d, e, 15);
4153   R1(e, a, b, c, d, 16);
4154   R1(d, e, a, b, c, 17);
4155   R1(c, d, e, a, b, 18);
4156   R1(b, c, d, e, a, 19);
4157   R2(a, b, c, d, e, 20);
4158   R2(e, a, b, c, d, 21);
4159   R2(d, e, a, b, c, 22);
4160   R2(c, d, e, a, b, 23);
4161   R2(b, c, d, e, a, 24);
4162   R2(a, b, c, d, e, 25);
4163   R2(e, a, b, c, d, 26);
4164   R2(d, e, a, b, c, 27);
4165   R2(c, d, e, a, b, 28);
4166   R2(b, c, d, e, a, 29);
4167   R2(a, b, c, d, e, 30);
4168   R2(e, a, b, c, d, 31);
4169   R2(d, e, a, b, c, 32);
4170   R2(c, d, e, a, b, 33);
4171   R2(b, c, d, e, a, 34);
4172   R2(a, b, c, d, e, 35);
4173   R2(e, a, b, c, d, 36);
4174   R2(d, e, a, b, c, 37);
4175   R2(c, d, e, a, b, 38);
4176   R2(b, c, d, e, a, 39);
4177   R3(a, b, c, d, e, 40);
4178   R3(e, a, b, c, d, 41);
4179   R3(d, e, a, b, c, 42);
4180   R3(c, d, e, a, b, 43);
4181   R3(b, c, d, e, a, 44);
4182   R3(a, b, c, d, e, 45);
4183   R3(e, a, b, c, d, 46);
4184   R3(d, e, a, b, c, 47);
4185   R3(c, d, e, a, b, 48);
4186   R3(b, c, d, e, a, 49);
4187   R3(a, b, c, d, e, 50);
4188   R3(e, a, b, c, d, 51);
4189   R3(d, e, a, b, c, 52);
4190   R3(c, d, e, a, b, 53);
4191   R3(b, c, d, e, a, 54);
4192   R3(a, b, c, d, e, 55);
4193   R3(e, a, b, c, d, 56);
4194   R3(d, e, a, b, c, 57);
4195   R3(c, d, e, a, b, 58);
4196   R3(b, c, d, e, a, 59);
4197   R4(a, b, c, d, e, 60);
4198   R4(e, a, b, c, d, 61);
4199   R4(d, e, a, b, c, 62);
4200   R4(c, d, e, a, b, 63);
4201   R4(b, c, d, e, a, 64);
4202   R4(a, b, c, d, e, 65);
4203   R4(e, a, b, c, d, 66);
4204   R4(d, e, a, b, c, 67);
4205   R4(c, d, e, a, b, 68);
4206   R4(b, c, d, e, a, 69);
4207   R4(a, b, c, d, e, 70);
4208   R4(e, a, b, c, d, 71);
4209   R4(d, e, a, b, c, 72);
4210   R4(c, d, e, a, b, 73);
4211   R4(b, c, d, e, a, 74);
4212   R4(a, b, c, d, e, 75);
4213   R4(e, a, b, c, d, 76);
4214   R4(d, e, a, b, c, 77);
4215   R4(c, d, e, a, b, 78);
4216   R4(b, c, d, e, a, 79);
4217   state[0] += a;
4218   state[1] += b;
4219   state[2] += c;
4220   state[3] += d;
4221   state[4] += e;
4222   /* Erase working structures. The order of operations is important,
4223    * used to ensure that compiler doesn't optimize those out. */
4224   memset(block, 0, sizeof(block));
4225   a = b = c = d = e = 0;
4226   (void) a;
4227   (void) b;
4228   (void) c;
4229   (void) d;
4230   (void) e;
4231 }
4232
4233 void mg_sha1_init(mg_sha1_ctx *context) {
4234   context->state[0] = 0x67452301;
4235   context->state[1] = 0xEFCDAB89;
4236   context->state[2] = 0x98BADCFE;
4237   context->state[3] = 0x10325476;
4238   context->state[4] = 0xC3D2E1F0;
4239   context->count[0] = context->count[1] = 0;
4240 }
4241
4242 void mg_sha1_update(mg_sha1_ctx *context, const unsigned char *data,
4243                     size_t len) {
4244   size_t i, j;
4245
4246   j = context->count[0];
4247   if ((context->count[0] += (uint32_t) len << 3) < j) context->count[1]++;
4248   context->count[1] += (uint32_t) (len >> 29);
4249   j = (j >> 3) & 63;
4250   if ((j + len) > 63) {
4251     memcpy(&context->buffer[j], data, (i = 64 - j));
4252     mg_sha1_transform(context->state, context->buffer);
4253     for (; i + 63 < len; i += 64) {
4254       mg_sha1_transform(context->state, &data[i]);
4255     }
4256     j = 0;
4257   } else
4258     i = 0;
4259   memcpy(&context->buffer[j], &data[i], len - i);
4260 }
4261
4262 void mg_sha1_final(unsigned char digest[20], mg_sha1_ctx *context) {
4263   unsigned i;
4264   unsigned char finalcount[8], c;
4265
4266   for (i = 0; i < 8; i++) {
4267     finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >>
4268                                       ((3 - (i & 3)) * 8)) &
4269                                      255);
4270   }
4271   c = 0200;
4272   mg_sha1_update(context, &c, 1);
4273   while ((context->count[0] & 504) != 448) {
4274     c = 0000;
4275     mg_sha1_update(context, &c, 1);
4276   }
4277   mg_sha1_update(context, finalcount, 8);
4278   for (i = 0; i < 20; i++) {
4279     digest[i] =
4280         (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
4281   }
4282   memset(context, '\0', sizeof(*context));
4283   memset(&finalcount, '\0', sizeof(finalcount));
4284 }
4285
4286 #ifdef MG_ENABLE_LINES
4287 #line 1 "src/sntp.c"
4288 #endif
4289
4290
4291
4292
4293
4294
4295 #define SNTP_TIME_OFFSET 2208988800U  // (1970 - 1900) in seconds
4296 #define SNTP_MAX_FRAC 4294967295.0    // 2 ** 32 - 1
4297
4298 static int64_t gettimestamp(const uint32_t *data) {
4299   uint32_t sec = mg_ntohl(data[0]), frac = mg_ntohl(data[1]);
4300   if (sec) sec -= SNTP_TIME_OFFSET;
4301   return ((int64_t) sec) * 1000 + (int64_t) (frac / SNTP_MAX_FRAC * 1000.0);
4302 }
4303
4304 int64_t mg_sntp_parse(const unsigned char *buf, size_t len) {
4305   int64_t res = -1;
4306   int mode = len > 0 ? buf[0] & 7 : 0;
4307   int version = len > 0 ? (buf[0] >> 3) & 7 : 0;
4308   if (len < 48) {
4309     MG_ERROR(("%s", "corrupt packet"));
4310   } else if (mode != 4 && mode != 5) {
4311     MG_ERROR(("%s", "not a server reply"));
4312   } else if (buf[1] == 0) {
4313     MG_ERROR(("%s", "server sent a kiss of death"));
4314   } else if (version == 4 || version == 3) {
4315     // int64_t ref = gettimestamp((uint32_t *) &buf[16]);
4316     int64_t t0 = gettimestamp((uint32_t *) &buf[24]);
4317     int64_t t1 = gettimestamp((uint32_t *) &buf[32]);
4318     int64_t t2 = gettimestamp((uint32_t *) &buf[40]);
4319     int64_t t3 = (int64_t) mg_millis();
4320     int64_t delta = (t3 - t0) - (t2 - t1);
4321     MG_VERBOSE(("%lld %lld %lld %lld delta:%lld", t0, t1, t2, t3, delta));
4322     res = t2 + delta / 2;
4323   } else {
4324     MG_ERROR(("unexpected version: %d", version));
4325   }
4326   return res;
4327 }
4328
4329 static void sntp_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
4330   if (ev == MG_EV_READ) {
4331     int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len);
4332     if (milliseconds > 0) {
4333       MG_INFO(("%lu got time: %lld ms from epoch", c->id, milliseconds));
4334       mg_call(c, MG_EV_SNTP_TIME, (uint64_t *) &milliseconds);
4335       MG_VERBOSE(("%u.%u", (unsigned) (milliseconds / 1000),
4336                   (unsigned) (milliseconds % 1000)));
4337     }
4338     mg_iobuf_del(&c->recv, 0, c->recv.len);  // Free receive buffer
4339   } else if (ev == MG_EV_CONNECT) {
4340     mg_sntp_request(c);
4341   } else if (ev == MG_EV_CLOSE) {
4342   }
4343   (void) fnd;
4344   (void) evd;
4345 }
4346
4347 void mg_sntp_request(struct mg_connection *c) {
4348   if (c->is_resolving) {
4349     MG_ERROR(("%lu wait until resolved", c->id));
4350   } else {
4351     int64_t now = (int64_t) mg_millis();  // Use int64_t, for vc98
4352     uint8_t buf[48] = {0};
4353     uint32_t *t = (uint32_t *) &buf[40];
4354     double frac = ((double) (now % 1000)) / 1000.0 * SNTP_MAX_FRAC;
4355     buf[0] = (0 << 6) | (4 << 3) | 3;
4356     t[0] = mg_htonl((uint32_t) (now / 1000) + SNTP_TIME_OFFSET);
4357     t[1] = mg_htonl((uint32_t) frac);
4358     mg_send(c, buf, sizeof(buf));
4359   }
4360 }
4361
4362 struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url,
4363                                       mg_event_handler_t fn, void *fnd) {
4364   struct mg_connection *c = NULL;
4365   if (url == NULL) url = "udp://time.google.com:123";
4366   if ((c = mg_connect(mgr, url, fn, fnd)) != NULL) c->pfn = sntp_cb;
4367   return c;
4368 }
4369
4370 #ifdef MG_ENABLE_LINES
4371 #line 1 "src/sock.c"
4372 #endif
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384 #if MG_ENABLE_SOCKET
4385
4386 #ifndef closesocket
4387 #define closesocket(x) close(x)
4388 #endif
4389
4390 #define FD(c_) ((MG_SOCKET_TYPE) (size_t) (c_)->fd)
4391 #define S2PTR(s_) ((void *) (size_t) (s_))
4392
4393 #ifndef MSG_NONBLOCKING
4394 #define MSG_NONBLOCKING 0
4395 #endif
4396
4397 #ifndef AF_INET6
4398 #define AF_INET6 10
4399 #endif
4400
4401 #ifndef MG_SOCK_ERR
4402 #define MG_SOCK_ERR(errcode) ((errcode) < 0 ? errno : 0)
4403 #endif
4404
4405 #ifndef MG_SOCK_INTR
4406 #define MG_SOCK_INTR(fd) (fd == MG_INVALID_SOCKET && MG_SOCK_ERR(-1) == EINTR)
4407 #endif
4408
4409 #ifndef MG_SOCK_PENDING
4410 #define MG_SOCK_PENDING(errcode) \
4411   (((errcode) < 0) && (errno == EINPROGRESS || errno == EWOULDBLOCK))
4412 #endif
4413
4414 #ifndef MG_SOCK_RESET
4415 #define MG_SOCK_RESET(errcode) \
4416   (((errcode) < 0) && (errno == EPIPE || errno == ECONNRESET))
4417 #endif
4418
4419 union usa {
4420   struct sockaddr sa;
4421   struct sockaddr_in sin;
4422 #if MG_ENABLE_IPV6
4423   struct sockaddr_in6 sin6;
4424 #endif
4425 };
4426
4427 static socklen_t tousa(struct mg_addr *a, union usa *usa) {
4428   socklen_t len = sizeof(usa->sin);
4429   memset(usa, 0, sizeof(*usa));
4430   usa->sin.sin_family = AF_INET;
4431   usa->sin.sin_port = a->port;
4432   *(uint32_t *) &usa->sin.sin_addr = a->ip;
4433 #if MG_ENABLE_IPV6
4434   if (a->is_ip6) {
4435     usa->sin.sin_family = AF_INET6;
4436     usa->sin6.sin6_port = a->port;
4437     memcpy(&usa->sin6.sin6_addr, a->ip6, sizeof(a->ip6));
4438     len = sizeof(usa->sin6);
4439   }
4440 #endif
4441   return len;
4442 }
4443
4444 static void tomgaddr(union usa *usa, struct mg_addr *a, bool is_ip6) {
4445   a->is_ip6 = is_ip6;
4446   a->port = usa->sin.sin_port;
4447   memcpy(&a->ip, &usa->sin.sin_addr, sizeof(a->ip));
4448 #if MG_ENABLE_IPV6
4449   if (is_ip6) {
4450     memcpy(a->ip6, &usa->sin6.sin6_addr, sizeof(a->ip6));
4451     a->port = usa->sin6.sin6_port;
4452   }
4453 #endif
4454 }
4455
4456 static void setlocaddr(MG_SOCKET_TYPE fd, struct mg_addr *addr) {
4457   union usa usa;
4458   socklen_t n = sizeof(usa);
4459   if (getsockname(fd, &usa.sa, &n) == 0) {
4460     tomgaddr(&usa, addr, n != sizeof(usa.sin));
4461   }
4462 }
4463
4464 static void iolog(struct mg_connection *c, char *buf, long n, bool r) {
4465   if (n == MG_IO_WAIT) {
4466     // Do nothing
4467   } else if (n <= 0) {
4468     c->is_closing = 1;  // Termination. Don't call mg_error(): #1529
4469   } else if (n > 0) {
4470     if (c->is_hexdumping) {
4471       union usa usa;
4472       socklen_t slen = sizeof(usa.sin);
4473       if (getsockname(FD(c), &usa.sa, &slen) < 0) (void) 0;  // Ignore result
4474       MG_INFO(("\n-- %lu %M %s %M %ld", c->id, mg_print_ip_port, &c->loc,
4475                r ? "<-" : "->", mg_print_ip_port, &c->rem, n));
4476
4477       mg_hexdump(buf, (size_t) n);
4478     }
4479     if (r) {
4480       c->recv.len += (size_t) n;
4481       mg_call(c, MG_EV_READ, &n);
4482     } else {
4483       mg_iobuf_del(&c->send, 0, (size_t) n);
4484       // if (c->send.len == 0) mg_iobuf_resize(&c->send, 0);
4485       if (c->send.len == 0) {
4486         MG_EPOLL_MOD(c, 0);
4487       }
4488       mg_call(c, MG_EV_WRITE, &n);
4489     }
4490   }
4491 }
4492
4493 long mg_io_send(struct mg_connection *c, const void *buf, size_t len) {
4494   long n;
4495   if (c->is_udp) {
4496     union usa usa;
4497     socklen_t slen = tousa(&c->rem, &usa);
4498     n = sendto(FD(c), (char *) buf, len, 0, &usa.sa, slen);
4499     if (n > 0) setlocaddr(FD(c), &c->loc);
4500   } else {
4501     n = send(FD(c), (char *) buf, len, MSG_NONBLOCKING);
4502   }
4503   if (MG_SOCK_PENDING(n)) return MG_IO_WAIT;
4504   if (MG_SOCK_RESET(n)) return MG_IO_RESET;
4505   if (n <= 0) return MG_IO_ERR;
4506   return n;
4507 }
4508
4509 bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
4510   if (c->is_udp) {
4511     long n = mg_io_send(c, buf, len);
4512     MG_DEBUG(("%lu %p %d:%d %ld err %d", c->id, c->fd, (int) c->send.len,
4513               (int) c->recv.len, n, MG_SOCK_ERR(n)));
4514     iolog(c, (char *) buf, n, false);
4515     return n > 0;
4516   } else {
4517     return mg_iobuf_add(&c->send, c->send.len, buf, len);
4518   }
4519 }
4520
4521 static void mg_set_non_blocking_mode(MG_SOCKET_TYPE fd) {
4522 #if defined(MG_CUSTOM_NONBLOCK)
4523   MG_CUSTOM_NONBLOCK(fd);
4524 #elif MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK
4525   unsigned long on = 1;
4526   ioctlsocket(fd, FIONBIO, &on);
4527 #elif MG_ENABLE_RL
4528   unsigned long on = 1;
4529   ioctlsocket(fd, FIONBIO, &on);
4530 #elif MG_ENABLE_FREERTOS_TCP
4531   const BaseType_t off = 0;
4532   if (setsockopt(fd, 0, FREERTOS_SO_RCVTIMEO, &off, sizeof(off)) != 0) (void) 0;
4533   if (setsockopt(fd, 0, FREERTOS_SO_SNDTIMEO, &off, sizeof(off)) != 0) (void) 0;
4534 #elif MG_ENABLE_LWIP
4535   lwip_fcntl(fd, F_SETFL, O_NONBLOCK);
4536 #elif MG_ARCH == MG_ARCH_AZURERTOS
4537   fcntl(fd, F_SETFL, O_NONBLOCK);
4538 #elif MG_ARCH == MG_ARCH_TIRTOS
4539   int val = 0;
4540   setsockopt(fd, SOL_SOCKET, SO_BLOCKING, &val, sizeof(val));
4541   // SPRU524J section 3.3.3 page 63, SO_SNDLOWAT
4542   int sz = sizeof(val);
4543   getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, &sz);
4544   val /= 2;  // set send low-water mark at half send buffer size
4545   setsockopt(fd, SOL_SOCKET, SO_SNDLOWAT, &val, sizeof(val));
4546 #else
4547   fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);  // Non-blocking mode
4548   fcntl(fd, F_SETFD, FD_CLOEXEC);                          // Set close-on-exec
4549 #endif
4550 }
4551
4552 bool mg_open_listener(struct mg_connection *c, const char *url) {
4553   MG_SOCKET_TYPE fd = MG_INVALID_SOCKET;
4554   bool success = false;
4555   c->loc.port = mg_htons(mg_url_port(url));
4556   if (!mg_aton(mg_url_host(url), &c->loc)) {
4557     MG_ERROR(("invalid listening URL: %s", url));
4558   } else {
4559     union usa usa;
4560     socklen_t slen = tousa(&c->loc, &usa);
4561     int rc, on = 1, af = c->loc.is_ip6 ? AF_INET6 : AF_INET;
4562     int type = strncmp(url, "udp:", 4) == 0 ? SOCK_DGRAM : SOCK_STREAM;
4563     int proto = type == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
4564     (void) on;
4565
4566     if ((fd = socket(af, type, proto)) == MG_INVALID_SOCKET) {
4567       MG_ERROR(("socket: %d", MG_SOCK_ERR(-1)));
4568 #if defined(SO_EXCLUSIVEADDRUSE)
4569     } else if ((rc = setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
4570                                 (char *) &on, sizeof(on))) != 0) {
4571       // "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE"
4572       MG_ERROR(("setsockopt(SO_EXCLUSIVEADDRUSE): %d %d", on, MG_SOCK_ERR(rc)));
4573 #elif defined(SO_REUSEADDR) && (!defined(LWIP_SOCKET) || SO_REUSE)
4574     } else if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
4575                                 sizeof(on))) != 0) {
4576       // 1. SO_REUSEADDR semantics on UNIX and Windows is different.  On
4577       // Windows, SO_REUSEADDR allows to bind a socket to a port without error
4578       // even if the port is already open by another program. This is not the
4579       // behavior SO_REUSEADDR was designed for, and leads to hard-to-track
4580       // failure scenarios.
4581       //
4582       // 2. For LWIP, SO_REUSEADDR should be explicitly enabled by defining
4583       // SO_REUSE = 1 in lwipopts.h, otherwise the code below will compile but
4584       // won't work! (setsockopt will return EINVAL)
4585       MG_ERROR(("setsockopt(SO_REUSEADDR): %d", MG_SOCK_ERR(rc)));
4586 #endif
4587 #if defined(IPV6_V6ONLY)
4588     } else if (c->loc.is_ip6 &&
4589                (rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &on,
4590                                 sizeof(on))) != 0) {
4591       // See #2089. Allow to bind v4 and v6 sockets on the same port
4592       MG_ERROR(("setsockopt(IPV6_V6ONLY): %d", MG_SOCK_ERR(rc)));
4593 #endif
4594     } else if ((rc = bind(fd, &usa.sa, slen)) != 0) {
4595       MG_ERROR(("bind: %d", MG_SOCK_ERR(rc)));
4596     } else if ((type == SOCK_STREAM &&
4597                 (rc = listen(fd, MG_SOCK_LISTEN_BACKLOG_SIZE)) != 0)) {
4598       // NOTE(lsm): FreeRTOS uses backlog value as a connection limit
4599       // In case port was set to 0, get the real port number
4600       MG_ERROR(("listen: %d", MG_SOCK_ERR(rc)));
4601     } else {
4602       setlocaddr(fd, &c->loc);
4603       mg_set_non_blocking_mode(fd);
4604       c->fd = S2PTR(fd);
4605       MG_EPOLL_ADD(c);
4606       success = true;
4607     }
4608   }
4609   if (success == false && fd != MG_INVALID_SOCKET) closesocket(fd);
4610   return success;
4611 }
4612
4613 long mg_io_recv(struct mg_connection *c, void *buf, size_t len) {
4614   long n = 0;
4615   if (c->is_udp) {
4616     union usa usa;
4617     socklen_t slen = tousa(&c->rem, &usa);
4618     n = recvfrom(FD(c), (char *) buf, len, 0, &usa.sa, &slen);
4619     if (n > 0) tomgaddr(&usa, &c->rem, slen != sizeof(usa.sin));
4620   } else {
4621     n = recv(FD(c), (char *) buf, len, MSG_NONBLOCKING);
4622   }
4623   if (MG_SOCK_PENDING(n)) return MG_IO_WAIT;
4624   if (MG_SOCK_RESET(n)) return MG_IO_RESET;
4625   if (n <= 0) return MG_IO_ERR;
4626   return n;
4627 }
4628
4629 // NOTE(lsm): do only one iteration of reads, cause some systems
4630 // (e.g. FreeRTOS stack) return 0 instead of -1/EWOULDBLOCK when no data
4631 static void read_conn(struct mg_connection *c) {
4632   long n = -1;
4633   if (c->recv.len >= MG_MAX_RECV_SIZE) {
4634     mg_error(c, "max_recv_buf_size reached");
4635   } else if (c->recv.size <= c->recv.len &&
4636              !mg_iobuf_resize(&c->recv, c->recv.size + MG_IO_SIZE)) {
4637     mg_error(c, "oom");
4638   } else {
4639     char *buf = (char *) &c->recv.buf[c->recv.len];
4640     size_t len = c->recv.size - c->recv.len;
4641     n = c->is_tls ? mg_tls_recv(c, buf, len) : mg_io_recv(c, buf, len);
4642     MG_DEBUG(("%lu %p snd %ld/%ld rcv %ld/%ld n=%ld err=%d", c->id, c->fd,
4643               (long) c->send.len, (long) c->send.size, (long) c->recv.len,
4644               (long) c->recv.size, n, MG_SOCK_ERR(n)));
4645     iolog(c, buf, n, true);
4646   }
4647 }
4648
4649 static void write_conn(struct mg_connection *c) {
4650   char *buf = (char *) c->send.buf;
4651   size_t len = c->send.len;
4652   long n = c->is_tls ? mg_tls_send(c, buf, len) : mg_io_send(c, buf, len);
4653   MG_DEBUG(("%lu %p snd %ld/%ld rcv %ld/%ld n=%ld err=%d", c->id, c->fd,
4654             (long) c->send.len, (long) c->send.size, (long) c->recv.len,
4655             (long) c->recv.size, n, MG_SOCK_ERR(n)));
4656   iolog(c, buf, n, false);
4657 }
4658
4659 static void close_conn(struct mg_connection *c) {
4660   if (FD(c) != MG_INVALID_SOCKET) {
4661 #if MG_ENABLE_EPOLL
4662     epoll_ctl(c->mgr->epoll_fd, EPOLL_CTL_DEL, FD(c), NULL);
4663 #endif
4664     closesocket(FD(c));
4665 #if MG_ENABLE_FREERTOS_TCP
4666     FreeRTOS_FD_CLR(c->fd, c->mgr->ss, eSELECT_ALL);
4667 #endif
4668   }
4669   mg_close_conn(c);
4670 }
4671
4672 static void connect_conn(struct mg_connection *c) {
4673   union usa usa;
4674   socklen_t n = sizeof(usa);
4675   // Use getpeername() to test whether we have connected
4676   if (getpeername(FD(c), &usa.sa, &n) == 0) {
4677     c->is_connecting = 0;
4678     mg_call(c, MG_EV_CONNECT, NULL);
4679     MG_EPOLL_MOD(c, 0);
4680     if (c->is_tls_hs) mg_tls_handshake(c);
4681   } else {
4682     mg_error(c, "socket error");
4683   }
4684 }
4685
4686 static void setsockopts(struct mg_connection *c) {
4687 #if MG_ENABLE_FREERTOS_TCP || MG_ARCH == MG_ARCH_AZURERTOS || \
4688     MG_ARCH == MG_ARCH_TIRTOS
4689   (void) c;
4690 #else
4691   int on = 1;
4692 #if !defined(SOL_TCP)
4693 #define SOL_TCP IPPROTO_TCP
4694 #endif
4695   if (setsockopt(FD(c), SOL_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) != 0)
4696     (void) 0;
4697   if (setsockopt(FD(c), SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)) !=
4698       0)
4699     (void) 0;
4700 #endif
4701 }
4702
4703 void mg_connect_resolved(struct mg_connection *c) {
4704   int type = c->is_udp ? SOCK_DGRAM : SOCK_STREAM;
4705   int rc, af = c->rem.is_ip6 ? AF_INET6 : AF_INET;  // c->rem has resolved IP
4706   c->fd = S2PTR(socket(af, type, 0));               // Create outbound socket
4707   c->is_resolving = 0;                              // Clear resolving flag
4708   if (FD(c) == MG_INVALID_SOCKET) {
4709     mg_error(c, "socket(): %d", MG_SOCK_ERR(-1));
4710   } else if (c->is_udp) {
4711     MG_EPOLL_ADD(c);
4712 #if MG_ARCH == MG_ARCH_TIRTOS
4713     union usa usa;  // TI-RTOS NDK requires binding to receive on UDP sockets
4714     socklen_t slen = tousa(&c->loc, &usa);
4715     if ((rc = bind(c->fd, &usa.sa, slen)) != 0)
4716       MG_ERROR(("bind: %d", MG_SOCK_ERR(rc)));
4717 #endif
4718     mg_call(c, MG_EV_RESOLVE, NULL);
4719     mg_call(c, MG_EV_CONNECT, NULL);
4720   } else {
4721     union usa usa;
4722     socklen_t slen = tousa(&c->rem, &usa);
4723     mg_set_non_blocking_mode(FD(c));
4724     setsockopts(c);
4725     MG_EPOLL_ADD(c);
4726     mg_call(c, MG_EV_RESOLVE, NULL);
4727     rc = connect(FD(c), &usa.sa, slen);  // Attempt to connect
4728     if (rc == 0) {                       // Success
4729       mg_call(c, MG_EV_CONNECT, NULL);   // Send MG_EV_CONNECT to the user
4730     } else if (MG_SOCK_PENDING(rc)) {    // Need to wait for TCP handshake
4731       MG_DEBUG(("%lu %p -> %M pend", c->id, c->fd, mg_print_ip_port, &c->rem));
4732       c->is_connecting = 1;
4733     } else {
4734       mg_error(c, "connect: %d", MG_SOCK_ERR(rc));
4735     }
4736   }
4737 }
4738
4739 static MG_SOCKET_TYPE raccept(MG_SOCKET_TYPE sock, union usa *usa,
4740                               socklen_t *len) {
4741   MG_SOCKET_TYPE fd = MG_INVALID_SOCKET;
4742   do {
4743     memset(usa, 0, sizeof(*usa));
4744     fd = accept(sock, &usa->sa, len);
4745   } while (MG_SOCK_INTR(fd));
4746   return fd;
4747 }
4748
4749 static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) {
4750   struct mg_connection *c = NULL;
4751   union usa usa;
4752   socklen_t sa_len = sizeof(usa);
4753   MG_SOCKET_TYPE fd = raccept(FD(lsn), &usa, &sa_len);
4754   if (fd == MG_INVALID_SOCKET) {
4755 #if MG_ARCH == MG_ARCH_AZURERTOS
4756     // AzureRTOS, in non-block socket mode can mark listening socket readable
4757     // even it is not. See comment for 'select' func implementation in
4758     // nx_bsd.c That's not an error, just should try later
4759     if (errno != EAGAIN)
4760 #endif
4761       MG_ERROR(("%lu accept failed, errno %d", lsn->id, MG_SOCK_ERR(-1)));
4762 #if (MG_ARCH != MG_ARCH_WIN32) && !MG_ENABLE_FREERTOS_TCP && \
4763     (MG_ARCH != MG_ARCH_TIRTOS) && !MG_ENABLE_POLL
4764   } else if ((long) fd >= FD_SETSIZE) {
4765     MG_ERROR(("%ld > %ld", (long) fd, (long) FD_SETSIZE));
4766     closesocket(fd);
4767 #endif
4768   } else if ((c = mg_alloc_conn(mgr)) == NULL) {
4769     MG_ERROR(("%lu OOM", lsn->id));
4770     closesocket(fd);
4771   } else {
4772     tomgaddr(&usa, &c->rem, sa_len != sizeof(usa.sin));
4773     LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
4774     c->fd = S2PTR(fd);
4775     MG_EPOLL_ADD(c);
4776     mg_set_non_blocking_mode(FD(c));
4777     setsockopts(c);
4778     c->is_accepted = 1;
4779     c->is_hexdumping = lsn->is_hexdumping;
4780     c->loc = lsn->loc;
4781     c->pfn = lsn->pfn;
4782     c->pfn_data = lsn->pfn_data;
4783     c->fn = lsn->fn;
4784     c->fn_data = lsn->fn_data;
4785     MG_DEBUG(("%lu %p accepted %M -> %M", c->id, c->fd, mg_print_ip_port,
4786               &c->rem, mg_print_ip_port, &c->loc));
4787     mg_call(c, MG_EV_OPEN, NULL);
4788     mg_call(c, MG_EV_ACCEPT, NULL);
4789   }
4790 }
4791
4792 static bool mg_socketpair(MG_SOCKET_TYPE sp[2], union usa usa[2], bool udp) {
4793   MG_SOCKET_TYPE sock;
4794   socklen_t n = sizeof(usa[0].sin);
4795   bool success = false;
4796
4797   sock = sp[0] = sp[1] = MG_INVALID_SOCKET;
4798   (void) memset(&usa[0], 0, sizeof(usa[0]));
4799   usa[0].sin.sin_family = AF_INET;
4800   *(uint32_t *) &usa->sin.sin_addr = mg_htonl(0x7f000001U);  // 127.0.0.1
4801   usa[1] = usa[0];
4802
4803   if (udp && (sp[0] = socket(AF_INET, SOCK_DGRAM, 0)) != MG_INVALID_SOCKET &&
4804       (sp[1] = socket(AF_INET, SOCK_DGRAM, 0)) != MG_INVALID_SOCKET &&
4805       bind(sp[0], &usa[0].sa, n) == 0 && bind(sp[1], &usa[1].sa, n) == 0 &&
4806       getsockname(sp[0], &usa[0].sa, &n) == 0 &&
4807       getsockname(sp[1], &usa[1].sa, &n) == 0 &&
4808       connect(sp[0], &usa[1].sa, n) == 0 &&
4809       connect(sp[1], &usa[0].sa, n) == 0) {
4810     success = true;
4811   } else if (!udp &&
4812              (sock = socket(AF_INET, SOCK_STREAM, 0)) != MG_INVALID_SOCKET &&
4813              bind(sock, &usa[0].sa, n) == 0 &&
4814              listen(sock, MG_SOCK_LISTEN_BACKLOG_SIZE) == 0 &&
4815              getsockname(sock, &usa[0].sa, &n) == 0 &&
4816              (sp[0] = socket(AF_INET, SOCK_STREAM, 0)) != MG_INVALID_SOCKET &&
4817              connect(sp[0], &usa[0].sa, n) == 0 &&
4818              (sp[1] = raccept(sock, &usa[1], &n)) != MG_INVALID_SOCKET) {
4819     success = true;
4820   }
4821   if (success) {
4822     mg_set_non_blocking_mode(sp[1]);
4823   } else {
4824     if (sp[0] != MG_INVALID_SOCKET) closesocket(sp[0]);
4825     if (sp[1] != MG_INVALID_SOCKET) closesocket(sp[1]);
4826     sp[0] = sp[1] = MG_INVALID_SOCKET;
4827   }
4828   if (sock != MG_INVALID_SOCKET) closesocket(sock);
4829   return success;
4830 }
4831
4832 int mg_mkpipe(struct mg_mgr *mgr, mg_event_handler_t fn, void *fn_data,
4833               bool udp) {
4834   union usa usa[2];
4835   MG_SOCKET_TYPE sp[2] = {MG_INVALID_SOCKET, MG_INVALID_SOCKET};
4836   struct mg_connection *c = NULL;
4837   if (!mg_socketpair(sp, usa, udp)) {
4838     MG_ERROR(("Cannot create socket pair"));
4839   } else if ((c = mg_wrapfd(mgr, (int) sp[1], fn, fn_data)) == NULL) {
4840     closesocket(sp[0]);
4841     closesocket(sp[1]);
4842     sp[0] = sp[1] = MG_INVALID_SOCKET;
4843   } else {
4844     tomgaddr(&usa[0], &c->rem, false);
4845     MG_DEBUG(("%lu %p pipe %lu", c->id, c->fd, (unsigned long) sp[0]));
4846   }
4847   return (int) sp[0];
4848 }
4849
4850 static bool can_read(const struct mg_connection *c) {
4851   return c->is_full == false;
4852 }
4853
4854 static bool can_write(const struct mg_connection *c) {
4855   return c->is_connecting || (c->send.len > 0 && c->is_tls_hs == 0);
4856 }
4857
4858 static bool skip_iotest(const struct mg_connection *c) {
4859   return (c->is_closing || c->is_resolving || FD(c) == MG_INVALID_SOCKET) ||
4860          (can_read(c) == false && can_write(c) == false);
4861 }
4862
4863 static void mg_iotest(struct mg_mgr *mgr, int ms) {
4864 #if MG_ENABLE_FREERTOS_TCP
4865   struct mg_connection *c;
4866   for (c = mgr->conns; c != NULL; c = c->next) {
4867     c->is_readable = c->is_writable = 0;
4868     if (skip_iotest(c)) continue;
4869     if (can_read(c))
4870       FreeRTOS_FD_SET(c->fd, mgr->ss, eSELECT_READ | eSELECT_EXCEPT);
4871     if (can_write(c)) FreeRTOS_FD_SET(c->fd, mgr->ss, eSELECT_WRITE);
4872   }
4873   FreeRTOS_select(mgr->ss, pdMS_TO_TICKS(ms));
4874   for (c = mgr->conns; c != NULL; c = c->next) {
4875     EventBits_t bits = FreeRTOS_FD_ISSET(c->fd, mgr->ss);
4876     c->is_readable = bits & (eSELECT_READ | eSELECT_EXCEPT) ? 1U : 0;
4877     c->is_writable = bits & eSELECT_WRITE ? 1U : 0;
4878     if (c->fd != MG_INVALID_SOCKET)
4879       FreeRTOS_FD_CLR(c->fd, mgr->ss,
4880                       eSELECT_READ | eSELECT_EXCEPT | eSELECT_WRITE);
4881   }
4882 #elif MG_ENABLE_EPOLL
4883   size_t max = 1;
4884   for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) {
4885     c->is_readable = c->is_writable = 0;
4886     if (mg_tls_pending(c) > 0) ms = 1, c->is_readable = 1;
4887     if (can_write(c)) MG_EPOLL_MOD(c, 1);
4888     max++;
4889   }
4890   struct epoll_event *evs = (struct epoll_event *) alloca(max * sizeof(evs[0]));
4891   int n = epoll_wait(mgr->epoll_fd, evs, (int) max, ms);
4892   for (int i = 0; i < n; i++) {
4893     struct mg_connection *c = (struct mg_connection *) evs[i].data.ptr;
4894     if (evs[i].events & EPOLLERR) {
4895       mg_error(c, "socket error");
4896     } else if (c->is_readable == 0) {
4897       bool rd = evs[i].events & (EPOLLIN | EPOLLHUP);
4898       bool wr = evs[i].events & EPOLLOUT;
4899       c->is_readable = can_read(c) && rd ? 1U : 0;
4900       c->is_writable = can_write(c) && wr ? 1U : 0;
4901     }
4902   }
4903   (void) skip_iotest;
4904 #elif MG_ENABLE_POLL
4905   nfds_t n = 0;
4906   for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) n++;
4907   struct pollfd *fds = (struct pollfd *) alloca(n * sizeof(fds[0]));
4908   memset(fds, 0, n * sizeof(fds[0]));
4909   n = 0;
4910   for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) {
4911     c->is_readable = c->is_writable = 0;
4912     if (skip_iotest(c)) {
4913       // Socket not valid, ignore
4914     } else if (mg_tls_pending(c) > 0) {
4915       ms = 1;  // Don't wait if TLS is ready
4916     } else {
4917       fds[n].fd = FD(c);
4918       if (can_read(c)) fds[n].events |= POLLIN;
4919       if (can_write(c)) fds[n].events |= POLLOUT;
4920       n++;
4921     }
4922   }
4923
4924   // MG_INFO(("poll n=%d ms=%d", (int) n, ms));
4925   if (poll(fds, n, ms) < 0) {
4926 #if MG_ARCH == MG_ARCH_WIN32
4927     if (n == 0) Sleep(ms);  // On Windows, poll fails if no sockets
4928 #endif
4929     memset(fds, 0, n * sizeof(fds[0]));
4930   }
4931   n = 0;
4932   for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) {
4933     if (skip_iotest(c)) {
4934       // Socket not valid, ignore
4935     } else if (mg_tls_pending(c) > 0) {
4936       c->is_readable = 1;
4937     } else {
4938       if (fds[n].revents & POLLERR) {
4939         mg_error(c, "socket error");
4940       } else {
4941         c->is_readable =
4942             (unsigned) (fds[n].revents & (POLLIN | POLLHUP) ? 1 : 0);
4943         c->is_writable = (unsigned) (fds[n].revents & POLLOUT ? 1 : 0);
4944       }
4945       n++;
4946     }
4947   }
4948 #else
4949   struct timeval tv = {ms / 1000, (ms % 1000) * 1000}, tv_zero = {0, 0}, *tvp;
4950   struct mg_connection *c;
4951   fd_set rset, wset, eset;
4952   MG_SOCKET_TYPE maxfd = 0;
4953   int rc;
4954
4955   FD_ZERO(&rset);
4956   FD_ZERO(&wset);
4957   FD_ZERO(&eset);
4958   tvp = ms < 0 ? NULL : &tv;
4959   for (c = mgr->conns; c != NULL; c = c->next) {
4960     c->is_readable = c->is_writable = 0;
4961     if (skip_iotest(c)) continue;
4962     FD_SET(FD(c), &eset);
4963     if (can_read(c)) FD_SET(FD(c), &rset);
4964     if (can_write(c)) FD_SET(FD(c), &wset);
4965     if (mg_tls_pending(c) > 0) tvp = &tv_zero;
4966     if (FD(c) > maxfd) maxfd = FD(c);
4967   }
4968
4969   if ((rc = select((int) maxfd + 1, &rset, &wset, &eset, tvp)) < 0) {
4970 #if MG_ARCH == MG_ARCH_WIN32
4971     if (maxfd == 0) Sleep(ms);  // On Windows, select fails if no sockets
4972 #else
4973     MG_ERROR(("select: %d %d", rc, MG_SOCK_ERR(rc)));
4974 #endif
4975     FD_ZERO(&rset);
4976     FD_ZERO(&wset);
4977     FD_ZERO(&eset);
4978   }
4979
4980   for (c = mgr->conns; c != NULL; c = c->next) {
4981     if (FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &eset)) {
4982       mg_error(c, "socket error");
4983     } else {
4984       c->is_readable = FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &rset);
4985       c->is_writable = FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &wset);
4986       if (mg_tls_pending(c) > 0) c->is_readable = 1;
4987     }
4988   }
4989 #endif
4990 }
4991
4992 void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
4993   struct mg_connection *c, *tmp;
4994   uint64_t now;
4995
4996   mg_iotest(mgr, ms);
4997   now = mg_millis();
4998   mg_timer_poll(&mgr->timers, now);
4999
5000   for (c = mgr->conns; c != NULL; c = tmp) {
5001     bool is_resp = c->is_resp;
5002     tmp = c->next;
5003     mg_call(c, MG_EV_POLL, &now);
5004     if (is_resp && !c->is_resp) {
5005       long n = 0;
5006       mg_call(c, MG_EV_READ, &n);
5007     }
5008     MG_VERBOSE(("%lu %c%c %c%c%c%c%c", c->id, c->is_readable ? 'r' : '-',
5009                 c->is_writable ? 'w' : '-', c->is_tls ? 'T' : 't',
5010                 c->is_connecting ? 'C' : 'c', c->is_tls_hs ? 'H' : 'h',
5011                 c->is_resolving ? 'R' : 'r', c->is_closing ? 'C' : 'c'));
5012     if (c->is_resolving || c->is_closing) {
5013       // Do nothing
5014     } else if (c->is_listening && c->is_udp == 0) {
5015       if (c->is_readable) accept_conn(mgr, c);
5016     } else if (c->is_connecting) {
5017       if (c->is_readable || c->is_writable) connect_conn(c);
5018     } else if (c->is_tls_hs) {
5019       if ((c->is_readable || c->is_writable)) mg_tls_handshake(c);
5020     } else {
5021       if (c->is_readable) read_conn(c);
5022       if (c->is_writable) write_conn(c);
5023     }
5024
5025     if (c->is_draining && c->send.len == 0) c->is_closing = 1;
5026     if (c->is_closing) close_conn(c);
5027   }
5028 }
5029 #endif
5030
5031 #ifdef MG_ENABLE_LINES
5032 #line 1 "src/ssi.c"
5033 #endif
5034
5035
5036
5037
5038 #ifndef MG_MAX_SSI_DEPTH
5039 #define MG_MAX_SSI_DEPTH 5
5040 #endif
5041
5042 #ifndef MG_SSI_BUFSIZ
5043 #define MG_SSI_BUFSIZ 1024
5044 #endif
5045
5046 #if MG_ENABLE_SSI
5047 static char *mg_ssi(const char *path, const char *root, int depth) {
5048   struct mg_iobuf b = {NULL, 0, 0, MG_IO_SIZE};
5049   FILE *fp = fopen(path, "rb");
5050   if (fp != NULL) {
5051     char buf[MG_SSI_BUFSIZ], arg[sizeof(buf)];
5052     int ch, intag = 0;
5053     size_t len = 0;
5054     buf[0] = arg[0] = '\0';
5055     while ((ch = fgetc(fp)) != EOF) {
5056       if (intag && ch == '>' && buf[len - 1] == '-' && buf[len - 2] == '-') {
5057         buf[len++] = (char) (ch & 0xff);
5058         buf[len] = '\0';
5059         if (sscanf(buf, "<!--#include file=\"%[^\"]", arg)) {
5060           char tmp[MG_PATH_MAX + MG_SSI_BUFSIZ + 10],
5061               *p = (char *) path + strlen(path), *data;
5062           while (p > path && p[-1] != MG_DIRSEP && p[-1] != '/') p--;
5063           mg_snprintf(tmp, sizeof(tmp), "%.*s%s", (int) (p - path), path, arg);
5064           if (depth < MG_MAX_SSI_DEPTH &&
5065               (data = mg_ssi(tmp, root, depth + 1)) != NULL) {
5066             mg_iobuf_add(&b, b.len, data, strlen(data));
5067             free(data);
5068           } else {
5069             MG_ERROR(("%s: file=%s error or too deep", path, arg));
5070           }
5071         } else if (sscanf(buf, "<!--#include virtual=\"%[^\"]", arg)) {
5072           char tmp[MG_PATH_MAX + MG_SSI_BUFSIZ + 10], *data;
5073           mg_snprintf(tmp, sizeof(tmp), "%s%s", root, arg);
5074           if (depth < MG_MAX_SSI_DEPTH &&
5075               (data = mg_ssi(tmp, root, depth + 1)) != NULL) {
5076             mg_iobuf_add(&b, b.len, data, strlen(data));
5077             free(data);
5078           } else {
5079             MG_ERROR(("%s: virtual=%s error or too deep", path, arg));
5080           }
5081         } else {
5082           // Unknown SSI tag
5083           MG_ERROR(("Unknown SSI tag: %.*s", (int) len, buf));
5084           mg_iobuf_add(&b, b.len, buf, len);
5085         }
5086         intag = 0;
5087         len = 0;
5088       } else if (ch == '<') {
5089         intag = 1;
5090         if (len > 0) mg_iobuf_add(&b, b.len, buf, len);
5091         len = 0;
5092         buf[len++] = (char) (ch & 0xff);
5093       } else if (intag) {
5094         if (len == 5 && strncmp(buf, "<!--#", 5) != 0) {
5095           intag = 0;
5096         } else if (len >= sizeof(buf) - 2) {
5097           MG_ERROR(("%s: SSI tag is too large", path));
5098           len = 0;
5099         }
5100         buf[len++] = (char) (ch & 0xff);
5101       } else {
5102         buf[len++] = (char) (ch & 0xff);
5103         if (len >= sizeof(buf)) {
5104           mg_iobuf_add(&b, b.len, buf, len);
5105           len = 0;
5106         }
5107       }
5108     }
5109     if (len > 0) mg_iobuf_add(&b, b.len, buf, len);
5110     if (b.len > 0) mg_iobuf_add(&b, b.len, "", 1);  // nul-terminate
5111     fclose(fp);
5112   }
5113   (void) depth;
5114   (void) root;
5115   return (char *) b.buf;
5116 }
5117
5118 void mg_http_serve_ssi(struct mg_connection *c, const char *root,
5119                        const char *fullpath) {
5120   const char *headers = "Content-Type: text/html; charset=utf-8\r\n";
5121   char *data = mg_ssi(fullpath, root, 0);
5122   mg_http_reply(c, 200, headers, "%s", data == NULL ? "" : data);
5123   free(data);
5124 }
5125 #else
5126 void mg_http_serve_ssi(struct mg_connection *c, const char *root,
5127                        const char *fullpath) {
5128   mg_http_reply(c, 501, NULL, "SSI not enabled");
5129   (void) root, (void) fullpath;
5130 }
5131 #endif
5132
5133 #ifdef MG_ENABLE_LINES
5134 #line 1 "src/str.c"
5135 #endif
5136
5137
5138 struct mg_str mg_str_s(const char *s) {
5139   struct mg_str str = {s, s == NULL ? 0 : strlen(s)};
5140   return str;
5141 }
5142
5143 struct mg_str mg_str_n(const char *s, size_t n) {
5144   struct mg_str str = {s, n};
5145   return str;
5146 }
5147
5148 int mg_lower(const char *s) {
5149   int c = *s;
5150   if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
5151   return c;
5152 }
5153
5154 int mg_ncasecmp(const char *s1, const char *s2, size_t len) {
5155   int diff = 0;
5156   if (len > 0) do {
5157       diff = mg_lower(s1++) - mg_lower(s2++);
5158     } while (diff == 0 && s1[-1] != '\0' && --len > 0);
5159   return diff;
5160 }
5161
5162 int mg_casecmp(const char *s1, const char *s2) {
5163   return mg_ncasecmp(s1, s2, (size_t) ~0);
5164 }
5165
5166 int mg_vcmp(const struct mg_str *s1, const char *s2) {
5167   size_t n2 = strlen(s2), n1 = s1->len;
5168   int r = strncmp(s1->ptr, s2, (n1 < n2) ? n1 : n2);
5169   if (r == 0) return (int) (n1 - n2);
5170   return r;
5171 }
5172
5173 int mg_vcasecmp(const struct mg_str *str1, const char *str2) {
5174   size_t n2 = strlen(str2), n1 = str1->len;
5175   int r = mg_ncasecmp(str1->ptr, str2, (n1 < n2) ? n1 : n2);
5176   if (r == 0) return (int) (n1 - n2);
5177   return r;
5178 }
5179
5180 struct mg_str mg_strdup(const struct mg_str s) {
5181   struct mg_str r = {NULL, 0};
5182   if (s.len > 0 && s.ptr != NULL) {
5183     char *sc = (char *) calloc(1, s.len + 1);
5184     if (sc != NULL) {
5185       memcpy(sc, s.ptr, s.len);
5186       sc[s.len] = '\0';
5187       r.ptr = sc;
5188       r.len = s.len;
5189     }
5190   }
5191   return r;
5192 }
5193
5194 int mg_strcmp(const struct mg_str str1, const struct mg_str str2) {
5195   size_t i = 0;
5196   while (i < str1.len && i < str2.len) {
5197     int c1 = str1.ptr[i];
5198     int c2 = str2.ptr[i];
5199     if (c1 < c2) return -1;
5200     if (c1 > c2) return 1;
5201     i++;
5202   }
5203   if (i < str1.len) return 1;
5204   if (i < str2.len) return -1;
5205   return 0;
5206 }
5207
5208 const char *mg_strstr(const struct mg_str haystack,
5209                       const struct mg_str needle) {
5210   size_t i;
5211   if (needle.len > haystack.len) return NULL;
5212   if (needle.len == 0) return haystack.ptr;
5213   for (i = 0; i <= haystack.len - needle.len; i++) {
5214     if (memcmp(haystack.ptr + i, needle.ptr, needle.len) == 0) {
5215       return haystack.ptr + i;
5216     }
5217   }
5218   return NULL;
5219 }
5220
5221 static bool is_space(int c) {
5222   return c == ' ' || c == '\r' || c == '\n' || c == '\t';
5223 }
5224
5225 struct mg_str mg_strstrip(struct mg_str s) {
5226   while (s.len > 0 && is_space((int) *s.ptr)) s.ptr++, s.len--;
5227   while (s.len > 0 && is_space((int) *(s.ptr + s.len - 1))) s.len--;
5228   return s;
5229 }
5230
5231 bool mg_match(struct mg_str s, struct mg_str p, struct mg_str *caps) {
5232   size_t i = 0, j = 0, ni = 0, nj = 0;
5233   if (caps) caps->ptr = NULL, caps->len = 0;
5234   while (i < p.len || j < s.len) {
5235     if (i < p.len && j < s.len && (p.ptr[i] == '?' || s.ptr[j] == p.ptr[i])) {
5236       if (caps == NULL) {
5237       } else if (p.ptr[i] == '?') {
5238         caps->ptr = &s.ptr[j], caps->len = 1;     // Finalize `?` cap
5239         caps++, caps->ptr = NULL, caps->len = 0;  // Init next cap
5240       } else if (caps->ptr != NULL && caps->len == 0) {
5241         caps->len = (size_t) (&s.ptr[j] - caps->ptr);  // Finalize current cap
5242         caps++, caps->len = 0, caps->ptr = NULL;       // Init next cap
5243       }
5244       i++, j++;
5245     } else if (i < p.len && (p.ptr[i] == '*' || p.ptr[i] == '#')) {
5246       if (caps && !caps->ptr) caps->len = 0, caps->ptr = &s.ptr[j];  // Init cap
5247       ni = i++, nj = j + 1;
5248     } else if (nj > 0 && nj <= s.len && (p.ptr[ni] == '#' || s.ptr[j] != '/')) {
5249       i = ni, j = nj;
5250       if (caps && caps->ptr == NULL && caps->len == 0) {
5251         caps--, caps->len = 0;  // Restart previous cap
5252       }
5253     } else {
5254       return false;
5255     }
5256   }
5257   if (caps && caps->ptr && caps->len == 0) {
5258     caps->len = (size_t) (&s.ptr[j] - caps->ptr);
5259   }
5260   return true;
5261 }
5262
5263 bool mg_globmatch(const char *s1, size_t n1, const char *s2, size_t n2) {
5264   return mg_match(mg_str_n(s2, n2), mg_str_n(s1, n1), NULL);
5265 }
5266
5267 static size_t mg_nce(const char *s, size_t n, size_t ofs, size_t *koff,
5268                      size_t *klen, size_t *voff, size_t *vlen, char delim) {
5269   size_t kvlen, kl;
5270   for (kvlen = 0; ofs + kvlen < n && s[ofs + kvlen] != delim;) kvlen++;
5271   for (kl = 0; kl < kvlen && s[ofs + kl] != '=';) kl++;
5272   if (koff != NULL) *koff = ofs;
5273   if (klen != NULL) *klen = kl;
5274   if (voff != NULL) *voff = kl < kvlen ? ofs + kl + 1 : 0;
5275   if (vlen != NULL) *vlen = kl < kvlen ? kvlen - kl - 1 : 0;
5276   ofs += kvlen + 1;
5277   return ofs > n ? n : ofs;
5278 }
5279
5280 bool mg_split(struct mg_str *s, struct mg_str *k, struct mg_str *v, char sep) {
5281   size_t koff = 0, klen = 0, voff = 0, vlen = 0, off = 0;
5282   if (s->ptr == NULL || s->len == 0) return 0;
5283   off = mg_nce(s->ptr, s->len, 0, &koff, &klen, &voff, &vlen, sep);
5284   if (k != NULL) *k = mg_str_n(s->ptr + koff, klen);
5285   if (v != NULL) *v = mg_str_n(s->ptr + voff, vlen);
5286   *s = mg_str_n(s->ptr + off, s->len - off);
5287   return off > 0;
5288 }
5289
5290 bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v) {
5291   return mg_split(s, k, v, ',');
5292 }
5293
5294 char *mg_hex(const void *buf, size_t len, char *to) {
5295   const unsigned char *p = (const unsigned char *) buf;
5296   const char *hex = "0123456789abcdef";
5297   size_t i = 0;
5298   for (; len--; p++) {
5299     to[i++] = hex[p[0] >> 4];
5300     to[i++] = hex[p[0] & 0x0f];
5301   }
5302   to[i] = '\0';
5303   return to;
5304 }
5305
5306 static unsigned char mg_unhex_nimble(unsigned char c) {
5307   return (c >= '0' && c <= '9')   ? (unsigned char) (c - '0')
5308          : (c >= 'A' && c <= 'F') ? (unsigned char) (c - '7')
5309                                   : (unsigned char) (c - 'W');
5310 }
5311
5312 unsigned long mg_unhexn(const char *s, size_t len) {
5313   unsigned long i = 0, v = 0;
5314   for (i = 0; i < len; i++) v <<= 4, v |= mg_unhex_nimble(((uint8_t *) s)[i]);
5315   return v;
5316 }
5317
5318 void mg_unhex(const char *buf, size_t len, unsigned char *to) {
5319   size_t i;
5320   for (i = 0; i < len; i += 2) {
5321     to[i >> 1] = (unsigned char) mg_unhexn(&buf[i], 2);
5322   }
5323 }
5324
5325 char *mg_remove_double_dots(char *s) {
5326   char *saved = s, *p = s;
5327   while (*s != '\0') {
5328     *p++ = *s++;
5329     if (s[-1] == '/' || s[-1] == '\\') {
5330       while (s[0] != '\0') {
5331         if (s[0] == '/' || s[0] == '\\') {
5332           s++;
5333         } else if (s[0] == '.' && s[1] == '.' &&
5334                    (s[2] == '/' || s[2] == '\\')) {
5335           s += 2;
5336         } else {
5337           break;
5338         }
5339       }
5340     }
5341   }
5342   *p = '\0';
5343   return saved;
5344 }
5345
5346 #ifdef MG_ENABLE_LINES
5347 #line 1 "src/timer.c"
5348 #endif
5349
5350
5351
5352 #define MG_TIMER_CALLED 4
5353
5354 void mg_timer_init(struct mg_timer **head, struct mg_timer *t, uint64_t ms,
5355                    unsigned flags, void (*fn)(void *), void *arg) {
5356   t->id = 0, t->period_ms = ms, t->expire = 0;
5357   t->flags = flags, t->fn = fn, t->arg = arg, t->next = *head;
5358   *head = t;
5359 }
5360
5361 void mg_timer_free(struct mg_timer **head, struct mg_timer *t) {
5362   while (*head && *head != t) head = &(*head)->next;
5363   if (*head) *head = t->next;
5364 }
5365
5366 // t: expiration time, prd: period, now: current time. Return true if expired
5367 bool mg_timer_expired(uint64_t *t, uint64_t prd, uint64_t now) {
5368   if (now + prd < *t) *t = 0;                    // Time wrapped? Reset timer
5369   if (*t == 0) *t = now + prd;                   // Firt poll? Set expiration
5370   if (*t > now) return false;                    // Not expired yet, return
5371   *t = (now - *t) > prd ? now + prd : *t + prd;  // Next expiration time
5372   return true;                                   // Expired, return true
5373 }
5374
5375 void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) {
5376   struct mg_timer *t, *tmp;
5377   for (t = *head; t != NULL; t = tmp) {
5378     bool once = t->expire == 0 && (t->flags & MG_TIMER_RUN_NOW) &&
5379                 !(t->flags & MG_TIMER_CALLED);  // Handle MG_TIMER_NOW only once
5380     bool expired = mg_timer_expired(&t->expire, t->period_ms, now_ms);
5381     tmp = t->next;
5382     if (!once && !expired) continue;
5383     if ((t->flags & MG_TIMER_REPEAT) || !(t->flags & MG_TIMER_CALLED)) {
5384       t->fn(t->arg);
5385     }
5386     t->flags |= MG_TIMER_CALLED;
5387   }
5388 }
5389
5390 #ifdef MG_ENABLE_LINES
5391 #line 1 "src/tls_dummy.c"
5392 #endif
5393
5394
5395 #if !MG_ENABLE_MBEDTLS && !MG_ENABLE_OPENSSL && !MG_ENABLE_CUSTOM_TLS
5396 void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
5397   (void) opts;
5398   mg_error(c, "TLS is not enabled");
5399 }
5400 void mg_tls_handshake(struct mg_connection *c) {
5401   (void) c;
5402 }
5403 void mg_tls_free(struct mg_connection *c) {
5404   (void) c;
5405 }
5406 long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
5407   return c == NULL || buf == NULL || len == 0 ? 0 : -1;
5408 }
5409 long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
5410   return c == NULL || buf == NULL || len == 0 ? 0 : -1;
5411 }
5412 size_t mg_tls_pending(struct mg_connection *c) {
5413   (void) c;
5414   return 0;
5415 }
5416 #endif
5417
5418 #ifdef MG_ENABLE_LINES
5419 #line 1 "src/tls_mbed.c"
5420 #endif
5421
5422
5423
5424
5425 #if MG_ENABLE_MBEDTLS
5426
5427 #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
5428 #define MGRNG , rng_get, NULL
5429 #else
5430 #define MGRNG
5431 #endif
5432
5433 void mg_tls_free(struct mg_connection *c) {
5434   struct mg_tls *tls = (struct mg_tls *) c->tls;
5435   if (tls != NULL) {
5436     free(tls->cafile);
5437     mbedtls_ssl_free(&tls->ssl);
5438     mbedtls_pk_free(&tls->pk);
5439     mbedtls_x509_crt_free(&tls->ca);
5440     mbedtls_x509_crt_free(&tls->cert);
5441     mbedtls_ssl_config_free(&tls->conf);
5442     free(tls);
5443     c->tls = NULL;
5444   }
5445 }
5446
5447 static int mg_net_send(void *ctx, const unsigned char *buf, size_t len) {
5448   long n = mg_io_send((struct mg_connection *) ctx, buf, len);
5449   MG_VERBOSE(("%lu n=%ld e=%d", ((struct mg_connection *) ctx)->id, n, errno));
5450   if (n == MG_IO_WAIT) return MBEDTLS_ERR_SSL_WANT_WRITE;
5451   if (n == MG_IO_RESET) return MBEDTLS_ERR_NET_CONN_RESET;
5452   if (n == MG_IO_ERR) return MBEDTLS_ERR_NET_SEND_FAILED;
5453   return (int) n;
5454 }
5455
5456 static int mg_net_recv(void *ctx, unsigned char *buf, size_t len) {
5457   long n = mg_io_recv((struct mg_connection *) ctx, buf, len);
5458   MG_VERBOSE(("%lu n=%ld", ((struct mg_connection *) ctx)->id, n));
5459   if (n == MG_IO_WAIT) return MBEDTLS_ERR_SSL_WANT_WRITE;
5460   if (n == MG_IO_RESET) return MBEDTLS_ERR_NET_CONN_RESET;
5461   if (n == MG_IO_ERR) return MBEDTLS_ERR_NET_RECV_FAILED;
5462   return (int) n;
5463 }
5464
5465 void mg_tls_handshake(struct mg_connection *c) {
5466   struct mg_tls *tls = (struct mg_tls *) c->tls;
5467   int rc = mbedtls_ssl_handshake(&tls->ssl);
5468   if (rc == 0) {  // Success
5469     MG_DEBUG(("%lu success", c->id));
5470     c->is_tls_hs = 0;
5471     mg_call(c, MG_EV_TLS_HS, NULL);
5472   } else if (rc == MBEDTLS_ERR_SSL_WANT_READ ||
5473              rc == MBEDTLS_ERR_SSL_WANT_WRITE) {  // Still pending
5474     MG_VERBOSE(("%lu pending, %d%d %d (-%#x)", c->id, c->is_connecting,
5475                 c->is_tls_hs, rc, -rc));
5476   } else {
5477     mg_error(c, "TLS handshake: -%#x", -rc);  // Error
5478   }
5479 }
5480
5481 static int mbed_rng(void *ctx, unsigned char *buf, size_t len) {
5482   mg_random(buf, len);
5483   (void) ctx;
5484   return 0;
5485 }
5486
5487 static void debug_cb(void *c, int lev, const char *s, int n, const char *s2) {
5488   n = (int) strlen(s2) - 1;
5489   MG_INFO(("%lu %d %.*s", ((struct mg_connection *) c)->id, lev, n, s2));
5490   (void) s;
5491 }
5492
5493 #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
5494 static int rng_get(void *p_rng, unsigned char *buf, size_t len) {
5495   (void) p_rng;
5496   mg_random(buf, len);
5497   return 0;
5498 }
5499 #endif
5500
5501 static struct mg_str mg_loadfile(struct mg_fs *fs, const char *path) {
5502   size_t n = 0;
5503   if (path[0] == '-') return mg_str(path);
5504   char *p = mg_file_read(fs, path, &n);
5505   return mg_str_n(p, n);
5506 }
5507
5508 void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
5509   struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
5510   struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
5511   int rc = 0;
5512   c->tls = tls;
5513   if (c->tls == NULL) {
5514     mg_error(c, "TLS OOM");
5515     goto fail;
5516   }
5517   MG_DEBUG(("%lu Setting TLS", c->id));
5518   mbedtls_ssl_init(&tls->ssl);
5519   mbedtls_ssl_config_init(&tls->conf);
5520   mbedtls_x509_crt_init(&tls->ca);
5521   mbedtls_x509_crt_init(&tls->cert);
5522   mbedtls_pk_init(&tls->pk);
5523   mbedtls_ssl_conf_dbg(&tls->conf, debug_cb, c);
5524 #if defined(MG_MBEDTLS_DEBUG_LEVEL)
5525   mbedtls_debug_set_threshold(MG_MBEDTLS_DEBUG_LEVEL);
5526 #endif
5527   if ((rc = mbedtls_ssl_config_defaults(
5528            &tls->conf,
5529            c->is_client ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
5530            MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
5531     mg_error(c, "tls defaults %#x", -rc);
5532     goto fail;
5533   }
5534   mbedtls_ssl_conf_rng(&tls->conf, mbed_rng, c);
5535   if (opts->ca == NULL || strcmp(opts->ca, "*") == 0) {
5536     mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE);
5537   } else if (opts->ca != NULL && opts->ca[0] != '\0') {
5538 #if defined(MBEDTLS_X509_CA_CHAIN_ON_DISK)
5539     tls->cafile = strdup(opts->ca);
5540     rc = mbedtls_ssl_conf_ca_chain_file(&tls->conf, tls->cafile, NULL);
5541     if (rc != 0) {
5542       mg_error(c, "parse on-disk chain(%s) err %#x", tls->cafile, -rc);
5543       goto fail;
5544     }
5545 #else
5546     struct mg_str s = mg_loadfile(fs, opts->ca);
5547     rc = mbedtls_x509_crt_parse(&tls->ca, (uint8_t *) s.ptr, s.len + 1);
5548     if (opts->ca[0] != '-') free((char *) s.ptr);
5549     if (rc != 0) {
5550       mg_error(c, "parse(%s) err %#x", opts->ca, -rc);
5551       goto fail;
5552     }
5553     mbedtls_ssl_conf_ca_chain(&tls->conf, &tls->ca, NULL);
5554 #endif
5555     if (opts->srvname.len > 0) {
5556       char *x = mg_mprintf("%.*s", (int) opts->srvname.len, opts->srvname.ptr);
5557       mbedtls_ssl_set_hostname(&tls->ssl, x);
5558       free(x);
5559     }
5560     mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
5561   }
5562   if (opts->cert != NULL && opts->cert[0] != '\0') {
5563     struct mg_str s = mg_loadfile(fs, opts->cert);
5564     const char *key = opts->certkey == NULL ? opts->cert : opts->certkey;
5565     rc = mbedtls_x509_crt_parse(&tls->cert, (uint8_t *) s.ptr, s.len + 1);
5566     if (opts->cert[0] != '-') free((char *) s.ptr);
5567     if (rc != 0) {
5568       mg_error(c, "parse(%s) err %#x", opts->cert, -rc);
5569       goto fail;
5570     }
5571     s = mg_loadfile(fs, key);
5572     rc = mbedtls_pk_parse_key(&tls->pk, (uint8_t *) s.ptr, s.len + 1, NULL,
5573                               0 MGRNG);
5574     if (key[0] != '-') free((char *) s.ptr);
5575     if (rc != 0) {
5576       mg_error(c, "tls key(%s) %#x", key, -rc);
5577       goto fail;
5578     }
5579     rc = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->cert, &tls->pk);
5580     if (rc != 0) {
5581       mg_error(c, "own cert %#x", -rc);
5582       goto fail;
5583     }
5584   }
5585   if ((rc = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) {
5586     mg_error(c, "setup err %#x", -rc);
5587     goto fail;
5588   }
5589   c->tls = tls;
5590   c->is_tls = 1;
5591   c->is_tls_hs = 1;
5592   mbedtls_ssl_set_bio(&tls->ssl, c, mg_net_send, mg_net_recv, 0);
5593   if (c->is_client && c->is_resolving == 0 && c->is_connecting == 0) {
5594     mg_tls_handshake(c);
5595   }
5596   return;
5597 fail:
5598   mg_tls_free(c);
5599 }
5600
5601 size_t mg_tls_pending(struct mg_connection *c) {
5602   struct mg_tls *tls = (struct mg_tls *) c->tls;
5603   return tls == NULL ? 0 : mbedtls_ssl_get_bytes_avail(&tls->ssl);
5604 }
5605
5606 long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
5607   struct mg_tls *tls = (struct mg_tls *) c->tls;
5608   long n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len);
5609   if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE)
5610     return MG_IO_WAIT;
5611   if (n <= 0) return MG_IO_ERR;
5612   return n;
5613 }
5614
5615 long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
5616   struct mg_tls *tls = (struct mg_tls *) c->tls;
5617   long n = mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf, len);
5618   if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE)
5619     return MG_IO_WAIT;
5620   if (n <= 0) return MG_IO_ERR;
5621   return n;
5622 }
5623 #endif
5624
5625 #ifdef MG_ENABLE_LINES
5626 #line 1 "src/tls_openssl.c"
5627 #endif
5628
5629
5630
5631 #if MG_ENABLE_OPENSSL
5632 static int mg_tls_err(struct mg_tls *tls, int res) {
5633   int err = SSL_get_error(tls->ssl, res);
5634   // We've just fetched the last error from the queue.
5635   // Now we need to clear the error queue. If we do not, then the following
5636   // can happen (actually reported):
5637   //  - A new connection is accept()-ed with cert error (e.g. self-signed cert)
5638   //  - Since all accept()-ed connections share listener's context,
5639   //  - *ALL* SSL accepted connection report read error on the next poll cycle.
5640   //    Thus a single errored connection can close all the rest, unrelated ones.
5641   // Clearing the error keeps the shared SSL_CTX in an OK state.
5642
5643   if (err != 0) ERR_print_errors_fp(stderr);
5644   ERR_clear_error();
5645   if (err == SSL_ERROR_WANT_READ) return 0;
5646   if (err == SSL_ERROR_WANT_WRITE) return 0;
5647   return err;
5648 }
5649
5650 void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
5651   struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
5652   const char *id = "mongoose";
5653   static unsigned char s_initialised = 0;
5654   int rc;
5655
5656   if (tls == NULL) {
5657     mg_error(c, "TLS OOM");
5658     goto fail;
5659   }
5660
5661   if (!s_initialised) {
5662     SSL_library_init();
5663     s_initialised++;
5664   }
5665   MG_DEBUG(("%lu Setting TLS, CA: %s, cert: %s, key: %s", c->id,
5666             opts->ca == NULL ? "null" : opts->ca,
5667             opts->cert == NULL ? "null" : opts->cert,
5668             opts->certkey == NULL ? "null" : opts->certkey));
5669   tls->ctx = c->is_client ? SSL_CTX_new(SSLv23_client_method())
5670                           : SSL_CTX_new(SSLv23_server_method());
5671   if ((tls->ssl = SSL_new(tls->ctx)) == NULL) {
5672     mg_error(c, "SSL_new");
5673     goto fail;
5674   }
5675   SSL_set_session_id_context(tls->ssl, (const uint8_t *) id,
5676                              (unsigned) strlen(id));
5677   // Disable deprecated protocols
5678   SSL_set_options(tls->ssl, SSL_OP_NO_SSLv2);
5679   SSL_set_options(tls->ssl, SSL_OP_NO_SSLv3);
5680   SSL_set_options(tls->ssl, SSL_OP_NO_TLSv1);
5681   SSL_set_options(tls->ssl, SSL_OP_NO_TLSv1_1);
5682 #ifdef MG_ENABLE_OPENSSL_NO_COMPRESSION
5683   SSL_set_options(tls->ssl, SSL_OP_NO_COMPRESSION);
5684 #endif
5685 #ifdef MG_ENABLE_OPENSSL_CIPHER_SERVER_PREFERENCE
5686   SSL_set_options(tls->ssl, SSL_OP_CIPHER_SERVER_PREFERENCE);
5687 #endif
5688
5689   if (opts->ca != NULL && opts->ca[0] != '\0') {
5690     SSL_set_verify(tls->ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
5691                    NULL);
5692     if ((rc = SSL_CTX_load_verify_locations(tls->ctx, opts->ca, NULL)) != 1) {
5693       mg_error(c, "load('%s') %d err %d", opts->ca, rc, mg_tls_err(tls, rc));
5694       goto fail;
5695     }
5696   }
5697   if (opts->cert != NULL && opts->cert[0] != '\0') {
5698     const char *key = opts->certkey;
5699     if (key == NULL) key = opts->cert;
5700     if ((rc = SSL_use_certificate_file(tls->ssl, opts->cert, 1)) != 1) {
5701       mg_error(c, "Invalid SSL cert, err %d", mg_tls_err(tls, rc));
5702       goto fail;
5703     } else if ((rc = SSL_use_PrivateKey_file(tls->ssl, key, 1)) != 1) {
5704       mg_error(c, "Invalid SSL key, err %d", mg_tls_err(tls, rc));
5705       goto fail;
5706 #if OPENSSL_VERSION_NUMBER > 0x10100000L
5707     } else if ((rc = SSL_use_certificate_chain_file(tls->ssl, opts->cert)) !=
5708                1) {
5709       mg_error(c, "Invalid chain, err %d", mg_tls_err(tls, rc));
5710       goto fail;
5711 #endif
5712     } else {
5713       SSL_set_mode(tls->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
5714 #if OPENSSL_VERSION_NUMBER > 0x10002000L
5715       SSL_set_ecdh_auto(tls->ssl, 1);
5716 #endif
5717     }
5718   }
5719   if (opts->ciphers != NULL) SSL_set_cipher_list(tls->ssl, opts->ciphers);
5720 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
5721   if (opts->srvname.len > 0) {
5722     char *s = mg_mprintf("%.*s", (int) opts->srvname.len, opts->srvname.ptr);
5723     SSL_set1_host(tls->ssl, s);
5724     SSL_set_tlsext_host_name(tls->ssl, s);
5725     free(s);
5726   }
5727 #endif
5728   c->tls = tls;
5729   c->is_tls = 1;
5730   c->is_tls_hs = 1;
5731   if (c->is_client && c->is_resolving == 0 && c->is_connecting == 0) {
5732     mg_tls_handshake(c);
5733   }
5734   MG_DEBUG(("%lu SSL %s OK", c->id, c->is_accepted ? "accept" : "client"));
5735   return;
5736 fail:
5737   c->is_closing = 1;
5738   free(tls);
5739 }
5740
5741 void mg_tls_handshake(struct mg_connection *c) {
5742   struct mg_tls *tls = (struct mg_tls *) c->tls;
5743   int rc;
5744   SSL_set_fd(tls->ssl, (int) (size_t) c->fd);
5745   rc = c->is_client ? SSL_connect(tls->ssl) : SSL_accept(tls->ssl);
5746   if (rc == 1) {
5747     MG_DEBUG(("%lu success", c->id));
5748     c->is_tls_hs = 0;
5749     mg_call(c, MG_EV_TLS_HS, NULL);
5750   } else {
5751     int code = mg_tls_err(tls, rc);
5752     if (code != 0) mg_error(c, "tls hs: rc %d, err %d", rc, code);
5753   }
5754 }
5755
5756 void mg_tls_free(struct mg_connection *c) {
5757   struct mg_tls *tls = (struct mg_tls *) c->tls;
5758   if (tls == NULL) return;
5759   SSL_free(tls->ssl);
5760   SSL_CTX_free(tls->ctx);
5761   free(tls);
5762   c->tls = NULL;
5763 }
5764
5765 size_t mg_tls_pending(struct mg_connection *c) {
5766   struct mg_tls *tls = (struct mg_tls *) c->tls;
5767   return tls == NULL ? 0 : (size_t) SSL_pending(tls->ssl);
5768 }
5769
5770 long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
5771   struct mg_tls *tls = (struct mg_tls *) c->tls;
5772   int n = SSL_read(tls->ssl, buf, (int) len);
5773   if (n < 0 && mg_tls_err(tls, n) == 0) return MG_IO_WAIT;
5774   if (n <= 0) return MG_IO_ERR;
5775   return n;
5776 }
5777
5778 long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
5779   struct mg_tls *tls = (struct mg_tls *) c->tls;
5780   int n = SSL_write(tls->ssl, buf, (int) len);
5781   if (n < 0 && mg_tls_err(tls, n) == 0) return MG_IO_WAIT;
5782   if (n <= 0) return MG_IO_ERR;
5783   return n;
5784 }
5785 #endif
5786
5787 #ifdef MG_ENABLE_LINES
5788 #line 1 "src/url.c"
5789 #endif
5790
5791
5792 struct url {
5793   size_t key, user, pass, host, port, uri, end;
5794 };
5795
5796 int mg_url_is_ssl(const char *url) {
5797   return strncmp(url, "wss:", 4) == 0 || strncmp(url, "https:", 6) == 0 ||
5798          strncmp(url, "mqtts:", 6) == 0 || strncmp(url, "ssl:", 4) == 0 ||
5799          strncmp(url, "tls:", 4) == 0;
5800 }
5801
5802 static struct url urlparse(const char *url) {
5803   size_t i;
5804   struct url u;
5805   memset(&u, 0, sizeof(u));
5806   for (i = 0; url[i] != '\0'; i++) {
5807     if (url[i] == '/' && i > 0 && u.host == 0 && url[i - 1] == '/') {
5808       u.host = i + 1;
5809       u.port = 0;
5810     } else if (url[i] == ']') {
5811       u.port = 0;  // IPv6 URLs, like http://[::1]/bar
5812     } else if (url[i] == ':' && u.port == 0 && u.uri == 0) {
5813       u.port = i + 1;
5814     } else if (url[i] == '@' && u.user == 0 && u.pass == 0 && u.uri == 0) {
5815       u.user = u.host;
5816       u.pass = u.port;
5817       u.host = i + 1;
5818       u.port = 0;
5819     } else if (url[i] == '/' && u.host && u.uri == 0) {
5820       u.uri = i;
5821     }
5822   }
5823   u.end = i;
5824 #if 0
5825   printf("[%s] %d %d %d %d %d\n", url, u.user, u.pass, u.host, u.port, u.uri);
5826 #endif
5827   return u;
5828 }
5829
5830 struct mg_str mg_url_host(const char *url) {
5831   struct url u = urlparse(url);
5832   size_t n = u.port  ? u.port - u.host - 1
5833              : u.uri ? u.uri - u.host
5834                      : u.end - u.host;
5835   struct mg_str s = mg_str_n(url + u.host, n);
5836   return s;
5837 }
5838
5839 const char *mg_url_uri(const char *url) {
5840   struct url u = urlparse(url);
5841   return u.uri ? url + u.uri : "/";
5842 }
5843
5844 unsigned short mg_url_port(const char *url) {
5845   struct url u = urlparse(url);
5846   unsigned short port = 0;
5847   if (strncmp(url, "http:", 5) == 0 || strncmp(url, "ws:", 3) == 0) port = 80;
5848   if (strncmp(url, "wss:", 4) == 0 || strncmp(url, "https:", 6) == 0)
5849     port = 443;
5850   if (strncmp(url, "mqtt:", 5) == 0) port = 1883;
5851   if (strncmp(url, "mqtts:", 6) == 0) port = 8883;
5852   if (u.port) port = (unsigned short) atoi(url + u.port);
5853   return port;
5854 }
5855
5856 struct mg_str mg_url_user(const char *url) {
5857   struct url u = urlparse(url);
5858   struct mg_str s = mg_str("");
5859   if (u.user && (u.pass || u.host)) {
5860     size_t n = u.pass ? u.pass - u.user - 1 : u.host - u.user - 1;
5861     s = mg_str_n(url + u.user, n);
5862   }
5863   return s;
5864 }
5865
5866 struct mg_str mg_url_pass(const char *url) {
5867   struct url u = urlparse(url);
5868   struct mg_str s = mg_str_n("", 0UL);
5869   if (u.pass && u.host) {
5870     size_t n = u.host - u.pass - 1;
5871     s = mg_str_n(url + u.pass, n);
5872   }
5873   return s;
5874 }
5875
5876 #ifdef MG_ENABLE_LINES
5877 #line 1 "src/util.c"
5878 #endif
5879
5880
5881 #if MG_ENABLE_CUSTOM_RANDOM
5882 #else
5883 void mg_random(void *buf, size_t len) {
5884   bool done = false;
5885   unsigned char *p = (unsigned char *) buf;
5886 #if MG_ARCH == MG_ARCH_ESP32
5887   while (len--) *p++ = (unsigned char) (esp_random() & 255);
5888   done = true;
5889 #elif MG_ARCH == MG_ARCH_WIN32
5890 #elif MG_ARCH == MG_ARCH_UNIX
5891   FILE *fp = fopen("/dev/urandom", "rb");
5892   if (fp != NULL) {
5893     if (fread(buf, 1, len, fp) == len) done = true;
5894     fclose(fp);
5895   }
5896 #endif
5897   // If everything above did not work, fallback to a pseudo random generator
5898   while (!done && len--) *p++ = (unsigned char) (rand() & 255);
5899 }
5900 #endif
5901
5902 char *mg_random_str(char *buf, size_t len) {
5903   size_t i;
5904   mg_random(buf, len);
5905   for (i = 0; i < len; i++) {
5906     uint8_t c = ((uint8_t *) buf)[i] % 62U;
5907     buf[i] = i == len - 1 ? (char) '\0'            // 0-terminate last byte
5908              : c < 26     ? (char) ('a' + c)       // lowercase
5909              : c < 52     ? (char) ('A' + c - 26)  // uppercase
5910                           : (char) ('0' + c - 52);     // numeric
5911   }
5912   return buf;
5913 }
5914
5915 uint32_t mg_ntohl(uint32_t net) {
5916   uint8_t data[4] = {0, 0, 0, 0};
5917   memcpy(&data, &net, sizeof(data));
5918   return (((uint32_t) data[3]) << 0) | (((uint32_t) data[2]) << 8) |
5919          (((uint32_t) data[1]) << 16) | (((uint32_t) data[0]) << 24);
5920 }
5921
5922 uint16_t mg_ntohs(uint16_t net) {
5923   uint8_t data[2] = {0, 0};
5924   memcpy(&data, &net, sizeof(data));
5925   return (uint16_t) ((uint16_t) data[1] | (((uint16_t) data[0]) << 8));
5926 }
5927
5928 uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) {
5929   static const uint32_t crclut[16] = {
5930       // table for polynomial 0xEDB88320 (reflected)
5931       0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, 0x76DC4190, 0x6B6B51F4,
5932       0x4DB26158, 0x5005713C, 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C,
5933       0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C};
5934   crc = ~crc;
5935   while (len--) {
5936     uint8_t byte = *(uint8_t *)buf++;
5937     crc = crclut[(crc ^ byte) & 0x0F] ^ (crc >> 4);
5938     crc = crclut[(crc ^ (byte >> 4)) & 0x0F] ^ (crc >> 4);
5939   }
5940   return ~crc;
5941 }
5942
5943 static int isbyte(int n) {
5944   return n >= 0 && n <= 255;
5945 }
5946
5947 static int parse_net(const char *spec, uint32_t *net, uint32_t *mask) {
5948   int n, a, b, c, d, slash = 32, len = 0;
5949   if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 ||
5950        sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) &&
5951       isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0 &&
5952       slash < 33) {
5953     len = n;
5954     *net = ((uint32_t) a << 24) | ((uint32_t) b << 16) | ((uint32_t) c << 8) |
5955            (uint32_t) d;
5956     *mask = slash ? (uint32_t) (0xffffffffU << (32 - slash)) : (uint32_t) 0;
5957   }
5958   return len;
5959 }
5960
5961 int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip) {
5962   struct mg_str k, v;
5963   int allowed = acl.len == 0 ? '+' : '-';  // If any ACL is set, deny by default
5964   while (mg_commalist(&acl, &k, &v)) {
5965     uint32_t net, mask;
5966     if (k.ptr[0] != '+' && k.ptr[0] != '-') return -1;
5967     if (parse_net(&k.ptr[1], &net, &mask) == 0) return -2;
5968     if ((mg_ntohl(remote_ip) & mask) == net) allowed = k.ptr[0];
5969   }
5970   return allowed == '+';
5971 }
5972
5973 #if MG_ENABLE_CUSTOM_MILLIS
5974 #else
5975 uint64_t mg_millis(void) {
5976 #if MG_ARCH == MG_ARCH_WIN32
5977   return GetTickCount();
5978 #elif MG_ARCH == MG_ARCH_RP2040
5979   return time_us_64() / 1000;
5980 #elif MG_ARCH == MG_ARCH_ESP32
5981   return esp_timer_get_time() / 1000;
5982 #elif MG_ARCH == MG_ARCH_ESP8266 || MG_ARCH == MG_ARCH_FREERTOS
5983   return xTaskGetTickCount() * portTICK_PERIOD_MS;
5984 #elif MG_ARCH == MG_ARCH_AZURERTOS
5985   return tx_time_get() * (1000 /* MS per SEC */ / TX_TIMER_TICKS_PER_SECOND);
5986 #elif MG_ARCH == MG_ARCH_TIRTOS
5987   return (uint64_t) Clock_getTicks();
5988 #elif MG_ARCH == MG_ARCH_ZEPHYR
5989   return (uint64_t) k_uptime_get();
5990 #elif MG_ARCH == MG_ARCH_CMSIS_RTOS1
5991   return (uint64_t)rt_time_get();
5992 #elif MG_ARCH == MG_ARCH_CMSIS_RTOS2
5993   return (uint64_t)((osKernelGetTickCount() * 1000) / osKernelGetTickFreq());
5994 #elif MG_ARCH == MG_ARCH_UNIX && defined(__APPLE__)
5995   // Apple CLOCK_MONOTONIC_RAW is equivalent to CLOCK_BOOTTIME on linux
5996   // Apple CLOCK_UPTIME_RAW is equivalent to CLOCK_MONOTONIC_RAW on linux
5997   return clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1000000;
5998 #elif MG_ARCH == MG_ARCH_UNIX
5999   struct timespec ts = {0, 0};
6000   // See #1615 - prefer monotonic clock
6001 #if defined(CLOCK_MONOTONIC_RAW)
6002   // Raw hardware-based time that is not subject to NTP adjustment
6003   clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
6004 #elif defined(CLOCK_MONOTONIC)
6005   // Affected by the incremental adjustments performed by adjtime and NTP
6006   clock_gettime(CLOCK_MONOTONIC, &ts);
6007 #else
6008   // Affected by discontinuous jumps in the system time and by the incremental
6009   // adjustments performed by adjtime and NTP
6010   clock_gettime(CLOCK_REALTIME, &ts);
6011 #endif
6012   return ((uint64_t) ts.tv_sec * 1000 + (uint64_t) ts.tv_nsec / 1000000);
6013 #elif defined(ARDUINO)
6014   return (uint64_t) millis();
6015 #else
6016   return (uint64_t) (time(NULL) * 1000);
6017 #endif
6018 }
6019 #endif
6020
6021 #ifdef MG_ENABLE_LINES
6022 #line 1 "src/ws.c"
6023 #endif
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035 struct ws_msg {
6036   uint8_t flags;
6037   size_t header_len;
6038   size_t data_len;
6039 };
6040
6041 size_t mg_ws_vprintf(struct mg_connection *c, int op, const char *fmt,
6042                      va_list *ap) {
6043   size_t len = c->send.len;
6044   size_t n = mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
6045   mg_ws_wrap(c, c->send.len - len, op);
6046   return n;
6047 }
6048
6049 size_t mg_ws_printf(struct mg_connection *c, int op, const char *fmt, ...) {
6050   size_t len = 0;
6051   va_list ap;
6052   va_start(ap, fmt);
6053   len = mg_ws_vprintf(c, op, fmt, &ap);
6054   va_end(ap);
6055   return len;
6056 }
6057
6058 static void ws_handshake(struct mg_connection *c, const struct mg_str *wskey,
6059                          const struct mg_str *wsproto, const char *fmt,
6060                          va_list *ap) {
6061   const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
6062   unsigned char sha[20], b64_sha[30];
6063
6064   mg_sha1_ctx sha_ctx;
6065   mg_sha1_init(&sha_ctx);
6066   mg_sha1_update(&sha_ctx, (unsigned char *) wskey->ptr, wskey->len);
6067   mg_sha1_update(&sha_ctx, (unsigned char *) magic, 36);
6068   mg_sha1_final(sha, &sha_ctx);
6069   mg_base64_encode(sha, sizeof(sha), (char *) b64_sha);
6070   mg_xprintf(mg_pfn_iobuf, &c->send,
6071              "HTTP/1.1 101 Switching Protocols\r\n"
6072              "Upgrade: websocket\r\n"
6073              "Connection: Upgrade\r\n"
6074              "Sec-WebSocket-Accept: %s\r\n",
6075              b64_sha);
6076   if (fmt != NULL) mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
6077   if (wsproto != NULL) {
6078     mg_printf(c, "Sec-WebSocket-Protocol: %.*s\r\n", (int) wsproto->len,
6079               wsproto->ptr);
6080   }
6081   mg_send(c, "\r\n", 2);
6082 }
6083
6084 static uint32_t be32(const uint8_t *p) {
6085   return (((uint32_t) p[3]) << 0) | (((uint32_t) p[2]) << 8) |
6086          (((uint32_t) p[1]) << 16) | (((uint32_t) p[0]) << 24);
6087 }
6088
6089 static size_t ws_process(uint8_t *buf, size_t len, struct ws_msg *msg) {
6090   size_t i, n = 0, mask_len = 0;
6091   memset(msg, 0, sizeof(*msg));
6092   if (len >= 2) {
6093     n = buf[1] & 0x7f;                // Frame length
6094     mask_len = buf[1] & 128 ? 4 : 0;  // last bit is a mask bit
6095     msg->flags = buf[0];
6096     if (n < 126 && len >= mask_len) {
6097       msg->data_len = n;
6098       msg->header_len = 2 + mask_len;
6099     } else if (n == 126 && len >= 4 + mask_len) {
6100       msg->header_len = 4 + mask_len;
6101       msg->data_len = (((size_t) buf[2]) << 8) | buf[3];
6102     } else if (len >= 10 + mask_len) {
6103       msg->header_len = 10 + mask_len;
6104       msg->data_len =
6105           (size_t) (((uint64_t) be32(buf + 2) << 32) + be32(buf + 6));
6106     }
6107   }
6108   // Sanity check, and integer overflow protection for the boundary check below
6109   // data_len should not be larger than 1 Gb
6110   if (msg->data_len > 1024 * 1024 * 1024) return 0;
6111   if (msg->header_len + msg->data_len > len) return 0;
6112   if (mask_len > 0) {
6113     uint8_t *p = buf + msg->header_len, *m = p - mask_len;
6114     for (i = 0; i < msg->data_len; i++) p[i] ^= m[i & 3];
6115   }
6116   return msg->header_len + msg->data_len;
6117 }
6118
6119 static size_t mkhdr(size_t len, int op, bool is_client, uint8_t *buf) {
6120   size_t n = 0;
6121   buf[0] = (uint8_t) (op | 128);
6122   if (len < 126) {
6123     buf[1] = (unsigned char) len;
6124     n = 2;
6125   } else if (len < 65536) {
6126     uint16_t tmp = mg_htons((uint16_t) len);
6127     buf[1] = 126;
6128     memcpy(&buf[2], &tmp, sizeof(tmp));
6129     n = 4;
6130   } else {
6131     uint32_t tmp;
6132     buf[1] = 127;
6133     tmp = mg_htonl((uint32_t) (((uint64_t) len) >> 32));
6134     memcpy(&buf[2], &tmp, sizeof(tmp));
6135     tmp = mg_htonl((uint32_t) (len & 0xffffffffU));
6136     memcpy(&buf[6], &tmp, sizeof(tmp));
6137     n = 10;
6138   }
6139   if (is_client) {
6140     buf[1] |= 1 << 7;  // Set masking flag
6141     mg_random(&buf[n], 4);
6142     n += 4;
6143   }
6144   return n;
6145 }
6146
6147 static void mg_ws_mask(struct mg_connection *c, size_t len) {
6148   if (c->is_client && c->send.buf != NULL) {
6149     size_t i;
6150     uint8_t *p = c->send.buf + c->send.len - len, *mask = p - 4;
6151     for (i = 0; i < len; i++) p[i] ^= mask[i & 3];
6152   }
6153 }
6154
6155 size_t mg_ws_send(struct mg_connection *c, const void *buf, size_t len,
6156                   int op) {
6157   uint8_t header[14];
6158   size_t header_len = mkhdr(len, op, c->is_client, header);
6159   mg_send(c, header, header_len);
6160   MG_VERBOSE(("WS out: %d [%.*s]", (int) len, (int) len, buf));
6161   mg_send(c, buf, len);
6162   mg_ws_mask(c, len);
6163   return header_len + len;
6164 }
6165
6166 static bool mg_ws_client_handshake(struct mg_connection *c) {
6167   int n = mg_http_get_request_len(c->recv.buf, c->recv.len);
6168   if (n < 0) {
6169     mg_error(c, "not http");  // Some just, not an HTTP request
6170   } else if (n > 0) {
6171     if (n < 15 || memcmp(c->recv.buf + 9, "101", 3) != 0) {
6172       mg_error(c, "handshake error");
6173     } else {
6174       struct mg_http_message hm;
6175       mg_http_parse((char *) c->recv.buf, c->recv.len, &hm);
6176       c->is_websocket = 1;
6177       mg_call(c, MG_EV_WS_OPEN, &hm);
6178     }
6179     mg_iobuf_del(&c->recv, 0, (size_t) n);
6180   } else {
6181     return true;  // Request is not yet received, quit event handler
6182   }
6183   return false;  // Continue event handler
6184 }
6185
6186 static void mg_ws_cb(struct mg_connection *c, int ev, void *ev_data,
6187                      void *fn_data) {
6188   struct ws_msg msg;
6189   size_t ofs = (size_t) c->pfn_data;
6190
6191   // assert(ofs < c->recv.len);
6192   if (ev == MG_EV_READ) {
6193     if (c->is_client && !c->is_websocket && mg_ws_client_handshake(c)) return;
6194
6195     while (ws_process(c->recv.buf + ofs, c->recv.len - ofs, &msg) > 0) {
6196       char *s = (char *) c->recv.buf + ofs + msg.header_len;
6197       struct mg_ws_message m = {{s, msg.data_len}, msg.flags};
6198       size_t len = msg.header_len + msg.data_len;
6199       uint8_t final = msg.flags & 128, op = msg.flags & 15;
6200       // MG_VERBOSE ("fin %d op %d len %d [%.*s]", final, op,
6201       //                       (int) m.data.len, (int) m.data.len, m.data.ptr));
6202       switch (op) {
6203         case WEBSOCKET_OP_CONTINUE:
6204           mg_call(c, MG_EV_WS_CTL, &m);
6205           break;
6206         case WEBSOCKET_OP_PING:
6207           MG_DEBUG(("%s", "WS PONG"));
6208           mg_ws_send(c, s, msg.data_len, WEBSOCKET_OP_PONG);
6209           mg_call(c, MG_EV_WS_CTL, &m);
6210           break;
6211         case WEBSOCKET_OP_PONG:
6212           mg_call(c, MG_EV_WS_CTL, &m);
6213           break;
6214         case WEBSOCKET_OP_TEXT:
6215         case WEBSOCKET_OP_BINARY:
6216           if (final) mg_call(c, MG_EV_WS_MSG, &m);
6217           break;
6218         case WEBSOCKET_OP_CLOSE:
6219           MG_DEBUG(("%lu WS CLOSE", c->id));
6220           mg_call(c, MG_EV_WS_CTL, &m);
6221           // Echo the payload of the received CLOSE message back to the sender
6222           mg_ws_send(c, m.data.ptr, m.data.len, WEBSOCKET_OP_CLOSE);
6223           c->is_draining = 1;
6224           break;
6225         default:
6226           // Per RFC6455, close conn when an unknown op is recvd
6227           mg_error(c, "unknown WS op %d", op);
6228           break;
6229       }
6230
6231       // Handle fragmented frames: strip header, keep in c->recv
6232       if (final == 0 || op == 0) {
6233         if (op) ofs++, len--, msg.header_len--;       // First frame
6234         mg_iobuf_del(&c->recv, ofs, msg.header_len);  // Strip header
6235         len -= msg.header_len;
6236         ofs += len;
6237         c->pfn_data = (void *) ofs;
6238         // MG_INFO(("FRAG %d [%.*s]", (int) ofs, (int) ofs, c->recv.buf));
6239       }
6240       // Remove non-fragmented frame
6241       if (final && op) mg_iobuf_del(&c->recv, ofs, len);
6242       // Last chunk of the fragmented frame
6243       if (final && !op) {
6244         m.flags = c->recv.buf[0];
6245         m.data = mg_str_n((char *) &c->recv.buf[1], (size_t) (ofs - 1));
6246         mg_call(c, MG_EV_WS_MSG, &m);
6247         mg_iobuf_del(&c->recv, 0, ofs);
6248         ofs = 0;
6249         c->pfn_data = NULL;
6250       }
6251     }
6252   }
6253   (void) fn_data;
6254   (void) ev_data;
6255 }
6256
6257 struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url,
6258                                     mg_event_handler_t fn, void *fn_data,
6259                                     const char *fmt, ...) {
6260   struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
6261   if (c != NULL) {
6262     char nonce[16], key[30];
6263     struct mg_str host = mg_url_host(url);
6264     mg_random(nonce, sizeof(nonce));
6265     mg_base64_encode((unsigned char *) nonce, sizeof(nonce), key);
6266     mg_xprintf(mg_pfn_iobuf, &c->send,
6267                "GET %s HTTP/1.1\r\n"
6268                "Upgrade: websocket\r\n"
6269                "Host: %.*s\r\n"
6270                "Connection: Upgrade\r\n"
6271                "Sec-WebSocket-Version: 13\r\n"
6272                "Sec-WebSocket-Key: %s\r\n",
6273                mg_url_uri(url), (int) host.len, host.ptr, key);
6274     if (fmt != NULL) {
6275       va_list ap;
6276       va_start(ap, fmt);
6277       mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &ap);
6278       va_end(ap);
6279     }
6280     mg_xprintf(mg_pfn_iobuf, &c->send, "\r\n");
6281     c->pfn = mg_ws_cb;
6282     c->pfn_data = NULL;
6283   }
6284   return c;
6285 }
6286
6287 void mg_ws_upgrade(struct mg_connection *c, struct mg_http_message *hm,
6288                    const char *fmt, ...) {
6289   struct mg_str *wskey = mg_http_get_header(hm, "Sec-WebSocket-Key");
6290   c->pfn = mg_ws_cb;
6291   c->pfn_data = NULL;
6292   if (wskey == NULL) {
6293     mg_http_reply(c, 426, "", "WS upgrade expected\n");
6294     c->is_draining = 1;
6295   } else {
6296     struct mg_str *wsproto = mg_http_get_header(hm, "Sec-WebSocket-Protocol");
6297     va_list ap;
6298     va_start(ap, fmt);
6299     ws_handshake(c, wskey, wsproto, fmt, &ap);
6300     va_end(ap);
6301     c->is_websocket = 1;
6302     c->is_resp = 0;
6303     mg_call(c, MG_EV_WS_OPEN, hm);
6304   }
6305 }
6306
6307 size_t mg_ws_wrap(struct mg_connection *c, size_t len, int op) {
6308   uint8_t header[14], *p;
6309   size_t header_len = mkhdr(len, op, c->is_client, header);
6310
6311   // NOTE: order of operations is important!
6312   mg_iobuf_add(&c->send, c->send.len, NULL, header_len);
6313   p = &c->send.buf[c->send.len - len];         // p points to data
6314   memmove(p, p - header_len, len);             // Shift data
6315   memcpy(p - header_len, header, header_len);  // Prepend header
6316   mg_ws_mask(c, len);                          // Mask data
6317
6318   return c->send.len;
6319 }
6320
6321 #ifdef MG_ENABLE_LINES
6322 #line 1 "src/tcpip/driver_nxpimxrt1020.c"
6323 #endif
6324
6325
6326 /*
6327  * Todo
6328  * This driver doesn't support 10M line autoconfiguration yet.
6329  * Packets aren't sent if the link negociated 10M line.
6330  * todo: MAC back auto reconfiguration.
6331  */
6332
6333 #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_IMXRT1020)
6334 struct imx_rt1020_enet {
6335 volatile uint32_t RESERVED0, EIR, EIMR, RESERVED1, RDAR, TDAR, RESERVED2[3], ECR, RESERVED3[6], MMFR, MSCR, RESERVED4[7], MIBC, RESERVED5[7], RCR, RESERVED6[15], TCR, RESERVED7[7], PALR, PAUR, OPD, TXIC0, TXIC1, TXIC2, RESERVED8, RXIC0, RXIC1, RXIC2, RESERVED9[3], IAUR, IALR, GAUR, GALR, RESERVED10[7], TFWR, RESERVED11[14], RDSR, TDSR, MRBR[2], RSFL, RSEM, RAEM, RAFL, TSEM, TAEM, TAFL, TIPG, FTRL, RESERVED12[3], TACC, RACC, RESERVED13[15], RMON_T_PACKETS, RMON_T_BC_PKT, RMON_T_MC_PKT, RMON_T_CRC_ALIGN, RMON_T_UNDERSIZE, RMON_T_OVERSIZE, RMON_T_FRAG, RMON_T_JAB, RMON_T_COL, RMON_T_P64, RMON_T_P65TO127, RMON_T_P128TO255, RMON_T_P256TO511, RMON_T_P512TO1023, RMON_T_P1024TO2048, RMON_T_GTE2048, RMON_T_OCTETS, IEEE_T_DROP, IEEE_T_FRAME_OK, IEEE_T_1COL, IEEE_T_MCOL, IEEE_T_DEF, IEEE_T_LCOL, IEEE_T_EXCOL, IEEE_T_MACERR, IEEE_T_CSERR, IEEE_T_SQE, IEEE_T_FDXFC, IEEE_T_OCTETS_OK, RESERVED14[3], RMON_R_PACKETS, RMON_R_BC_PKT, RMON_R_MC_PKT, RMON_R_CRC_ALIGN, RMON_R_UNDERSIZE, RMON_R_OVERSIZE, RMON_R_FRAG, RMON_R_JAB, RESERVED15, RMON_R_P64, RMON_R_P65TO127, RMON_R_P128TO255, RMON_R_P256TO511, RMON_R_P512TO1023, RMON_R_P1024TO2047, RMON_R_GTE2048, RMON_R_OCTETS, IEEE_R_DROP, IEEE_R_FRAME_OK, IEEE_R_CRC, IEEE_R_ALIGN, IEEE_R_MACERR, IEEE_R_FDXFC, IEEE_R_OCTETS_OK, RESERVED16[71], ATCR, ATVR, ATOFF, ATPER, ATCOR, ATINC, ATSTMP, RESERVED17[122], TGSR, TCSR0, TCCR0, TCSR1, TCCR1, TCSR2, TCCR2, TCSR3;
6336 };
6337
6338 #undef ENET
6339 #define ENET ((struct imx_rt1020_enet *) (uintptr_t) 0x402D8000u)
6340
6341 #undef BIT
6342 #define BIT(x) ((uint32_t) 1 << (x))
6343
6344 #define ENET_RXBUFF_SIZE 1536 // 1522 Buffer must be 64bits aligned
6345 #define ENET_TXBUFF_SIZE 1536 // 1522 hence set to 0x600 (1536)
6346 #define ENET_RXBD_NUM          (4)
6347 #define ENET_TXBD_NUM          (4)
6348
6349 const uint32_t EIMR_RX_ERR = 0x2400000;              // Intr mask RXF+EBERR
6350
6351 void ETH_IRQHandler(void);
6352 static bool mg_tcpip_driver_imxrt1020_init(struct mg_tcpip_if *ifp);
6353 static void wait_phy_complete(void);
6354 static struct mg_tcpip_if *s_ifp;                         // MIP interface
6355
6356 static size_t mg_tcpip_driver_imxrt1020_tx(const void *, size_t , struct mg_tcpip_if *);
6357 static bool mg_tcpip_driver_imxrt1020_up(struct mg_tcpip_if *ifp);
6358
6359 enum { IMXRT1020_PHY_ADDR = 0x02, IMXRT1020_PHY_BCR = 0, IMXRT1020_PHY_BSR = 1 };     // PHY constants
6360
6361 void delay(uint32_t);
6362 void delay (uint32_t di) {
6363   volatile int dno = 0; // Prevent optimization
6364   for (uint32_t i = 0; i < di; i++)
6365     for (int j=0; j<20; j++) // PLLx20 (500 MHz/24MHz)
6366       dno++;
6367 }
6368
6369 static void wait_phy_complete(void) {
6370   delay(0x00010000);
6371   const uint32_t delay_max = 0x00100000;
6372   uint32_t delay_cnt = 0;
6373   while (!(ENET->EIR & BIT(23)) && (delay_cnt < delay_max))
6374   {delay_cnt++;}
6375   ENET->EIR |= BIT(23); // MII interrupt clear
6376 }
6377
6378 static uint32_t imxrt1020_eth_read_phy(uint8_t addr, uint8_t reg) {
6379   ENET->EIR |= BIT(23); // MII interrupt clear
6380   uint32_t mask_phy_adr_reg = 0x1f; // 0b00011111: Ensure we write 5 bits (Phy address & register)
6381   uint32_t phy_transaction = 0x00;
6382   phy_transaction = (0x1 << 30) \
6383                   | (0x2 << 28) \
6384                   | ((uint32_t)(addr & mask_phy_adr_reg) << 23) \
6385                   | ((uint32_t)(reg & mask_phy_adr_reg)  << 18) \
6386                   | (0x2 << 16);
6387
6388   ENET->MMFR = phy_transaction;
6389   wait_phy_complete();
6390
6391   return (ENET->MMFR & 0x0000ffff);
6392 }
6393
6394 static void imxrt1020_eth_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
6395   ENET->EIR |= BIT(23); // MII interrupt clear
6396   uint8_t mask_phy_adr_reg = 0x1f; // 0b00011111: Ensure we write 5 bits (Phy address & register)
6397   uint32_t mask_phy_data = 0x0000ffff; // Ensure we write 16 bits (data)
6398   addr &= mask_phy_adr_reg;
6399   reg &= mask_phy_adr_reg;
6400   val &= mask_phy_data;
6401   uint32_t phy_transaction = 0x00;
6402   phy_transaction = (uint32_t)(0x1 << 30) \
6403                   | (uint32_t)(0x1 << 28) \
6404                   | (uint32_t)(addr << 23) \
6405                   | (uint32_t)(reg  << 18) \
6406                   | (uint32_t)(0x2 << 16) \
6407                   | (uint32_t)(val);
6408   ENET->MMFR = phy_transaction;
6409   wait_phy_complete();
6410 }
6411
6412 // FEC RX/TX descriptors (Enhanced descriptor not enabled)
6413 // Descriptor buffer structure, little endian
6414
6415 typedef struct enet_bd_struct_def
6416 {
6417     uint16_t length;  // Data length
6418     uint16_t control; // Control and status
6419     uint32_t *buffer; // Data ptr
6420 } enet_bd_struct_t;
6421
6422 // Descriptor and buffer globals, in non-cached area, 64 bits aligned.
6423
6424 __attribute__((section("NonCacheable,\"aw\",%nobits @"))) enet_bd_struct_t rx_buffer_descriptor[(ENET_RXBD_NUM)] __attribute__((aligned((64U))));
6425 __attribute__((section("NonCacheable,\"aw\",%nobits @"))) enet_bd_struct_t tx_buffer_descriptor[(ENET_TXBD_NUM)] __attribute__((aligned((64U))));
6426
6427 uint8_t rx_data_buffer[(ENET_RXBD_NUM)][((unsigned int)(((ENET_RXBUFF_SIZE)) + (((64U))-1U)) & (unsigned int)(~(unsigned int)(((64U))-1U)))] __attribute__((aligned((64U))));
6428 uint8_t tx_data_buffer[(ENET_TXBD_NUM)][((unsigned int)(((ENET_TXBUFF_SIZE)) + (((64U))-1U)) & (unsigned int)(~(unsigned int)(((64U))-1U)))] __attribute__((aligned((64U))));
6429
6430 // Initialise driver imx_rt1020
6431
6432 // static bool mg_tcpip_driver_imxrt1020_init(uint8_t *mac, void *data) { // VO
6433 static bool mg_tcpip_driver_imxrt1020_init(struct mg_tcpip_if *ifp) {
6434
6435   struct mg_tcpip_driver_imxrt1020_data *d = (struct mg_tcpip_driver_imxrt1020_data *) ifp->driver_data;
6436   s_ifp = ifp;
6437
6438   // ENET Reset, wait complete
6439   ENET->ECR |= BIT(0);
6440   while((ENET->ECR & BIT(0)) != 0) {}
6441
6442   // Re-latches the pin strapping pin values
6443   ENET->ECR |= BIT(0);
6444   while((ENET->ECR & BIT(0)) != 0) {}
6445
6446   // Setup MII/RMII MDC clock divider (<= 2.5MHz).
6447   ENET->MSCR = 0x130; // HOLDTIME 2 clk, Preamble enable, MDC MII_Speed Div 0x30
6448   imxrt1020_eth_write_phy(IMXRT1020_PHY_ADDR, IMXRT1020_PHY_BCR, 0x8000); // PHY W @0x00 D=0x8000 Soft reset
6449   while (imxrt1020_eth_read_phy(IMXRT1020_PHY_ADDR, IMXRT1020_PHY_BSR) & BIT(15)) {delay(0x5000);} // Wait finished poll 10ms
6450
6451   // PHY: Start Link
6452   {
6453     imxrt1020_eth_write_phy(IMXRT1020_PHY_ADDR, IMXRT1020_PHY_BCR, 0x1200); // PHY W @0x00 D=0x1200 Autonego enable + start
6454     imxrt1020_eth_write_phy(IMXRT1020_PHY_ADDR, 0x1f, 0x8180);    // PHY W @0x1f D=0x8180 Ref clock 50 MHz at XI input
6455
6456     uint32_t bcr = imxrt1020_eth_read_phy(IMXRT1020_PHY_ADDR, IMXRT1020_PHY_BCR);
6457     bcr &= ~BIT(10); // Isolation -> Normal
6458     imxrt1020_eth_write_phy(IMXRT1020_PHY_ADDR, IMXRT1020_PHY_BCR, bcr);
6459   }
6460
6461   // Disable ENET
6462   ENET->ECR = 0x0; //  Disable before configuration
6463
6464   // Configure ENET
6465   ENET->RCR = 0x05ee0104; // #CRCFWD=0 (CRC kept in frame) + RMII + MII Enable
6466   
6467   ENET->TCR = BIT(8) | BIT(2); // Addins (MAC address from PAUR+PALR) + Full duplex enable
6468   //ENET->TFWR = BIT(8); // Store And Forward Enable, 64 bytes (minimize tx latency)
6469
6470   // Configure descriptors and buffers
6471   // RX
6472   for (int i = 0; i < ENET_RXBD_NUM; i++) {
6473     // Wrap last descriptor buffer ptr
6474     rx_buffer_descriptor[i].control = (BIT(15) | ((i<(ENET_RXBD_NUM-1))?0:BIT(13))); // E+(W*)
6475     rx_buffer_descriptor[i].buffer = (uint32_t *)rx_data_buffer[i];
6476   }
6477
6478   // TX
6479   for (int i = 0; i < ENET_TXBD_NUM; i++) {
6480     // Wrap last descriptor buffer ptr
6481     tx_buffer_descriptor[i].control = ((i<(ENET_RXBD_NUM-1))?0:BIT(13)) | BIT(10); // (W*)+TC
6482     tx_buffer_descriptor[i].buffer = (uint32_t *)tx_data_buffer[i];
6483   }
6484
6485   // Continue ENET configuration
6486   ENET->RDSR = (uint32_t)(uintptr_t)rx_buffer_descriptor;
6487   ENET->TDSR = (uint32_t)(uintptr_t)tx_buffer_descriptor;
6488   ENET->MRBR[0] = ENET_RXBUFF_SIZE; // Same size for RX/TX buffers
6489
6490   // MAC address filtering (bytes in reversed order)
6491   ENET->PAUR = ((uint32_t) ifp->mac[4] << 24U) | (uint32_t) ifp->mac[5] << 16U;
6492   ENET->PALR = (uint32_t) (ifp->mac[0] << 24U) | ((uint32_t) ifp->mac[1] << 16U) |
6493                  ((uint32_t) ifp->mac[2] << 8U) | ifp->mac[3];
6494
6495   // Init Hash tables (mac filtering)
6496   ENET->IAUR = 0; // Unicast
6497   ENET->IALR = 0;
6498   ENET->GAUR = 0; // Multicast
6499   ENET->GALR = 0;
6500
6501   // Set ENET Online
6502   ENET->ECR |= BIT(8); // ENET Set Little-endian + (FEC buffer desc.)
6503   ENET->ECR |= BIT(1); // Enable
6504
6505   // Set interrupt mask
6506   ENET->EIMR = EIMR_RX_ERR;
6507
6508   // RX Descriptor activation
6509   ENET->RDAR = BIT(24); // Activate Receive Descriptor
6510   return true;
6511 }
6512
6513 // Transmit frame
6514 static uint32_t s_rt1020_txno;
6515
6516 static size_t mg_tcpip_driver_imxrt1020_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
6517
6518   if (len > sizeof(tx_data_buffer[ENET_TXBD_NUM])) {
6519   //  MG_ERROR(("Frame too big, %ld", (long) len));
6520     len = 0;  // Frame is too big
6521   } else if ((tx_buffer_descriptor[s_rt1020_txno].control & BIT(15))) {
6522   MG_ERROR(("No free descriptors"));
6523     // printf("D0 %lx SR %lx\n", (long) s_txdesc[0][0], (long) ETH->DMASR);
6524     len = 0;  // All descriptors are busy, fail
6525   } else {
6526     memcpy(tx_data_buffer[s_rt1020_txno], buf, len);     // Copy data
6527     tx_buffer_descriptor[s_rt1020_txno].length = (uint16_t) len;  // Set data len
6528     tx_buffer_descriptor[s_rt1020_txno].control |= (uint16_t)(BIT(10)); // TC (transmit CRC)
6529     //  tx_buffer_descriptor[s_rt1020_txno].control &= (uint16_t)(BIT(14) | BIT(12)); // Own doesn't affect HW
6530     tx_buffer_descriptor[s_rt1020_txno].control |= (uint16_t)(BIT(15) | BIT(11)); // R+L (ready+last)
6531     ENET->TDAR = BIT(24); // Descriptor updated. Hand over to DMA.
6532     // INFO
6533     // Relevant Descriptor bits: 15(R)  Ready
6534     //                           11(L)  last in frame
6535     //                           10(TC) transmis CRC
6536     // __DSB(); // ARM errata 838869 Cortex-M4, M4F, M7, M7F: "store immediate overlapping
6537                 // exception" return might vector to incorrect interrupt.
6538     if (++s_rt1020_txno >= ENET_TXBD_NUM) s_rt1020_txno = 0;
6539   }
6540   (void) ifp;
6541   return len;
6542 }
6543
6544 // IRQ (RX)
6545 static uint32_t s_rt1020_rxno;
6546
6547 void ENET_IRQHandler(void) {
6548   ENET->EIMR = 0;           // Mask interrupts.
6549   uint32_t eir = ENET->EIR; // Read EIR
6550   ENET->EIR = 0xffffffff;   // Clear interrupts
6551
6552   if (eir & EIMR_RX_ERR) // Global mask used
6553   {
6554     if (rx_buffer_descriptor[s_rt1020_rxno].control & BIT(15)) {
6555       ENET->EIMR = EIMR_RX_ERR; // Enable interrupts
6556       return;  // Empty? -> exit.
6557     }
6558     // Read inframes
6559     else { // Frame received, loop
6560       for (uint32_t i = 0; i < 10; i++) {  // read as they arrive but not forever
6561         if (rx_buffer_descriptor[s_rt1020_rxno].control & BIT(15)) break;  // exit when done
6562         // Process if CRC OK and frame not truncated
6563         if (!(rx_buffer_descriptor[s_rt1020_rxno].control & (BIT(2) | BIT(0)))) {
6564           uint32_t len = (rx_buffer_descriptor[s_rt1020_rxno].length);
6565           mg_tcpip_qwrite(rx_buffer_descriptor[s_rt1020_rxno].buffer, len > 4 ? len - 4 : len, s_ifp);
6566         }
6567         rx_buffer_descriptor[s_rt1020_rxno].control |= BIT(15); // Inform DMA RX is empty
6568         if (++s_rt1020_rxno >= ENET_RXBD_NUM) s_rt1020_rxno = 0;
6569       }
6570     }
6571   }
6572   ENET->EIMR = EIMR_RX_ERR; // Enable interrupts
6573 }
6574
6575 // Up/down status
6576 static bool mg_tcpip_driver_imxrt1020_up(struct mg_tcpip_if *ifp) {
6577   uint32_t bsr = imxrt1020_eth_read_phy(IMXRT1020_PHY_ADDR, IMXRT1020_PHY_BSR);
6578   (void) ifp;
6579   return bsr & BIT(2) ? 1 : 0;
6580 }
6581
6582 // API
6583 struct mg_tcpip_driver mg_tcpip_driver_imxrt1020 = {
6584   mg_tcpip_driver_imxrt1020_init, mg_tcpip_driver_imxrt1020_tx, NULL,
6585   mg_tcpip_driver_imxrt1020_up};
6586
6587 #endif
6588
6589 #ifdef MG_ENABLE_LINES
6590 #line 1 "src/tcpip/driver_stm32.c"
6591 #endif
6592
6593
6594 #if MG_ENABLE_TCPIP && MG_ENABLE_DRIVER_STM32
6595 struct stm32_eth {
6596   volatile uint32_t MACCR, MACFFR, MACHTHR, MACHTLR, MACMIIAR, MACMIIDR, MACFCR,
6597       MACVLANTR, RESERVED0[2], MACRWUFFR, MACPMTCSR, RESERVED1, MACDBGR, MACSR,
6598       MACIMR, MACA0HR, MACA0LR, MACA1HR, MACA1LR, MACA2HR, MACA2LR, MACA3HR,
6599       MACA3LR, RESERVED2[40], MMCCR, MMCRIR, MMCTIR, MMCRIMR, MMCTIMR,
6600       RESERVED3[14], MMCTGFSCCR, MMCTGFMSCCR, RESERVED4[5], MMCTGFCR,
6601       RESERVED5[10], MMCRFCECR, MMCRFAECR, RESERVED6[10], MMCRGUFCR,
6602       RESERVED7[334], PTPTSCR, PTPSSIR, PTPTSHR, PTPTSLR, PTPTSHUR, PTPTSLUR,
6603       PTPTSAR, PTPTTHR, PTPTTLR, RESERVED8, PTPTSSR, PTPPPSCR, RESERVED9[564],
6604       DMABMR, DMATPDR, DMARPDR, DMARDLAR, DMATDLAR, DMASR, DMAOMR, DMAIER,
6605       DMAMFBOCR, DMARSWTR, RESERVED10[8], DMACHTDR, DMACHRDR, DMACHTBAR,
6606       DMACHRBAR;
6607 };
6608 #undef ETH
6609 #define ETH ((struct stm32_eth *) (uintptr_t) 0x40028000)
6610
6611 #undef BIT
6612 #define BIT(x) ((uint32_t) 1 << (x))
6613 #define ETH_PKT_SIZE 1540  // Max frame size
6614 #define ETH_DESC_CNT 4     // Descriptors count
6615 #define ETH_DS 4           // Descriptor size (words)
6616
6617 static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS];      // RX descriptors
6618 static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS];      // TX descriptors
6619 static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE];  // RX ethernet buffers
6620 static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE];  // TX ethernet buffers
6621 static uint8_t s_txno;                               // Current TX descriptor
6622 static uint8_t s_rxno;                               // Current RX descriptor
6623
6624 static struct mg_tcpip_if *s_ifp;  // MIP interface
6625 enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1, PHY_CSCR = 31 };
6626
6627 static uint32_t eth_read_phy(uint8_t addr, uint8_t reg) {
6628   ETH->MACMIIAR &= (7 << 2);
6629   ETH->MACMIIAR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6);
6630   ETH->MACMIIAR |= BIT(0);
6631   while (ETH->MACMIIAR & BIT(0)) (void) 0;
6632   return ETH->MACMIIDR;
6633 }
6634
6635 static void eth_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
6636   ETH->MACMIIDR = val;
6637   ETH->MACMIIAR &= (7 << 2);
6638   ETH->MACMIIAR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | BIT(1);
6639   ETH->MACMIIAR |= BIT(0);
6640   while (ETH->MACMIIAR & BIT(0)) (void) 0;
6641 }
6642
6643 static uint32_t get_hclk(void) {
6644   struct rcc {
6645     volatile uint32_t CR, PLLCFGR, CFGR;
6646   } *rcc = (struct rcc *) 0x40023800;
6647   uint32_t clk = 0, hsi = 16000000 /* 16 MHz */, hse = 8000000 /* 8MHz */;
6648
6649   if (rcc->CFGR & (1 << 2)) {
6650     clk = hse;
6651   } else if (rcc->CFGR & (1 << 3)) {
6652     uint32_t vco, m, n, p;
6653     m = (rcc->PLLCFGR & (0x3f << 0)) >> 0;
6654     n = (rcc->PLLCFGR & (0x1ff << 6)) >> 6;
6655     p = (((rcc->PLLCFGR & (3 << 16)) >> 16) + 1) * 2;
6656     clk = (rcc->PLLCFGR & (1 << 22)) ? hse : hsi;
6657     vco = (uint32_t) ((uint64_t) clk * n / m);
6658     clk = vco / p;
6659   } else {
6660     clk = hsi;
6661   }
6662   uint32_t hpre = (rcc->CFGR & (15 << 4)) >> 4;
6663   if (hpre < 8) return clk;
6664
6665   uint8_t ahbptab[8] = {1, 2, 3, 4, 6, 7, 8, 9};  // log2(div)
6666   return ((uint32_t) clk) >> ahbptab[hpre - 8];
6667 }
6668
6669 //  Guess CR from HCLK. MDC clock is generated from HCLK (AHB); as per 802.3,
6670 //  it must not exceed 2.5MHz As the AHB clock can be (and usually is) derived
6671 //  from the HSI (internal RC), and it can go above specs, the datasheets
6672 //  specify a range of frequencies and activate one of a series of dividers to
6673 //  keep the MDC clock safely below 2.5MHz. We guess a divider setting based on
6674 //  HCLK with a +5% drift. If the user uses a different clock from our
6675 //  defaults, needs to set the macros on top Valid for STM32F74xxx/75xxx
6676 //  (38.8.1) and STM32F42xxx/43xxx (33.8.1) (both 4.5% worst case drift)
6677 static int guess_mdc_cr(void) {
6678   uint8_t crs[] = {2, 3, 0, 1, 4, 5};          // ETH->MACMIIAR::CR values
6679   uint8_t div[] = {16, 26, 42, 62, 102, 124};  // Respective HCLK dividers
6680   uint32_t hclk = get_hclk();                  // Guess system HCLK
6681   int result = -1;                             // Invalid CR value
6682   if (hclk < 25000000) {
6683     MG_ERROR(("HCLK too low"));
6684   } else {
6685     for (int i = 0; i < 6; i++) {
6686       if (hclk / div[i] <= 2375000UL /* 2.5MHz - 5% */) {
6687         result = crs[i];
6688         break;
6689       }
6690     }
6691     if (result < 0) MG_ERROR(("HCLK too high"));
6692   }
6693   MG_DEBUG(("HCLK: %u, CR: %d", hclk, result));
6694   return result;
6695 }
6696
6697 static bool mg_tcpip_driver_stm32_init(struct mg_tcpip_if *ifp) {
6698   struct mg_tcpip_driver_stm32_data *d =
6699       (struct mg_tcpip_driver_stm32_data *) ifp->driver_data;
6700   s_ifp = ifp;
6701
6702   // Init RX descriptors
6703   for (int i = 0; i < ETH_DESC_CNT; i++) {
6704     s_rxdesc[i][0] = BIT(31);                            // Own
6705     s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | BIT(14);       // 2nd address chained
6706     s_rxdesc[i][2] = (uint32_t) (uintptr_t) s_rxbuf[i];  // Point to data buffer
6707     s_rxdesc[i][3] =
6708         (uint32_t) (uintptr_t) s_rxdesc[(i + 1) % ETH_DESC_CNT];  // Chain
6709   }
6710
6711   // Init TX descriptors
6712   for (int i = 0; i < ETH_DESC_CNT; i++) {
6713     s_txdesc[i][2] = (uint32_t) (uintptr_t) s_txbuf[i];  // Buf pointer
6714     s_txdesc[i][3] =
6715         (uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT];  // Chain
6716   }
6717
6718   ETH->DMABMR |= BIT(0);                         // Software reset
6719   while ((ETH->DMABMR & BIT(0)) != 0) (void) 0;  // Wait until done
6720
6721   // Set MDC clock divider. If user told us the value, use it. Otherwise, guess
6722   int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
6723   ETH->MACMIIAR = ((uint32_t) cr & 7) << 2;
6724
6725   // NOTE(cpq): we do not use extended descriptor bit 7, and do not use
6726   // hardware checksum. Therefore, descriptor size is 4, not 8
6727   // ETH->DMABMR = BIT(13) | BIT(16) | BIT(22) | BIT(23) | BIT(25);
6728   ETH->MACIMR = BIT(3) | BIT(9);  // Mask timestamp & PMT IT
6729   ETH->MACFCR = BIT(7);           // Disable zero quarta pause
6730   // ETH->MACFFR = BIT(31);                            // Receive all
6731   eth_write_phy(PHY_ADDR, PHY_BCR, BIT(15));           // Reset PHY
6732   eth_write_phy(PHY_ADDR, PHY_BCR, BIT(12));           // Set autonegotiation
6733   ETH->DMARDLAR = (uint32_t) (uintptr_t) s_rxdesc;     // RX descriptors
6734   ETH->DMATDLAR = (uint32_t) (uintptr_t) s_txdesc;     // RX descriptors
6735   ETH->DMAIER = BIT(6) | BIT(16);                      // RIE, NISE
6736   ETH->MACCR = BIT(2) | BIT(3) | BIT(11) | BIT(14);    // RE, TE, Duplex, Fast
6737   ETH->DMAOMR = BIT(1) | BIT(13) | BIT(21) | BIT(25);  // SR, ST, TSF, RSF
6738
6739   // MAC address filtering
6740   ETH->MACA0HR = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
6741   ETH->MACA0LR = (uint32_t) (ifp->mac[3] << 24) |
6742                  ((uint32_t) ifp->mac[2] << 16) |
6743                  ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0];
6744   return true;
6745 }
6746
6747 static size_t mg_tcpip_driver_stm32_tx(const void *buf, size_t len,
6748                                        struct mg_tcpip_if *ifp) {
6749   if (len > sizeof(s_txbuf[s_txno])) {
6750     MG_ERROR(("Frame too big, %ld", (long) len));
6751     len = 0;  // Frame is too big
6752   } else if ((s_txdesc[s_txno][0] & BIT(31))) {
6753     ifp->nerr++;
6754     MG_ERROR(("No free descriptors"));
6755     // printf("D0 %lx SR %lx\n", (long) s_txdesc[0][0], (long) ETH->DMASR);
6756     len = 0;  // All descriptors are busy, fail
6757   } else {
6758     memcpy(s_txbuf[s_txno], buf, len);     // Copy data
6759     s_txdesc[s_txno][1] = (uint32_t) len;  // Set data len
6760     s_txdesc[s_txno][0] = BIT(20) | BIT(28) | BIT(29) | BIT(30);  // Chain,FS,LS
6761     s_txdesc[s_txno][0] |= BIT(31);  // Set OWN bit - let DMA take over
6762     if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
6763   }
6764   ETH->DMASR = BIT(2) | BIT(5);  // Clear any prior TBUS/TUS
6765   ETH->DMATPDR = 0;              // and resume
6766   return len;
6767 }
6768
6769 static bool mg_tcpip_driver_stm32_up(struct mg_tcpip_if *ifp) {
6770   uint32_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR);
6771   bool up = bsr & BIT(2) ? 1 : 0;
6772   if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) {  // link state just went up
6773     uint32_t scsr = eth_read_phy(PHY_ADDR, PHY_CSCR);
6774     uint32_t maccr = ETH->MACCR | BIT(14) | BIT(11);  // 100M, Full-duplex
6775     if ((scsr & BIT(3)) == 0) maccr &= ~BIT(14);      // 10M
6776     if ((scsr & BIT(4)) == 0) maccr &= ~BIT(11);      // Half-duplex
6777     ETH->MACCR = maccr;  // IRQ handler does not fiddle with this register
6778     MG_DEBUG(("Link is %uM %s-duplex", maccr & BIT(14) ? 100 : 10,
6779               maccr & BIT(11) ? "full" : "half"));
6780   }
6781   return up;
6782 }
6783
6784 void ETH_IRQHandler(void);
6785 void ETH_IRQHandler(void) {
6786   if (ETH->DMASR & BIT(6)) {             // Frame received, loop
6787     ETH->DMASR = BIT(16) | BIT(6);       // Clear flag
6788     for (uint32_t i = 0; i < 10; i++) {  // read as they arrive but not forever
6789       if (s_rxdesc[s_rxno][0] & BIT(31)) break;  // exit when done
6790       if (((s_rxdesc[s_rxno][0] & (BIT(8) | BIT(9))) == (BIT(8) | BIT(9))) &&
6791           !(s_rxdesc[s_rxno][0] & BIT(15))) {  // skip partial/errored frames
6792         uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (BIT(14) - 1));
6793         //  printf("%lx %lu %lx %.8lx\n", s_rxno, len, s_rxdesc[s_rxno][0],
6794         //  ETH->DMASR);
6795         mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
6796       }
6797       s_rxdesc[s_rxno][0] = BIT(31);
6798       if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
6799     }
6800   }
6801   ETH->DMASR = BIT(7);  // Clear possible RBUS while processing
6802   ETH->DMARPDR = 0;     // and resume RX
6803 }
6804
6805 struct mg_tcpip_driver mg_tcpip_driver_stm32 = {mg_tcpip_driver_stm32_init,
6806                                                 mg_tcpip_driver_stm32_tx, NULL,
6807                                                 mg_tcpip_driver_stm32_up};
6808 #endif
6809
6810 #ifdef MG_ENABLE_LINES
6811 #line 1 "src/tcpip/driver_stm32h.c"
6812 #endif
6813
6814
6815 #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_STM32H) && \
6816     MG_ENABLE_DRIVER_STM32H
6817 struct stm32h_eth {
6818   volatile uint32_t MACCR, MACECR, MACPFR, MACWTR, MACHT0R, MACHT1R,
6819       RESERVED1[14], MACVTR, RESERVED2, MACVHTR, RESERVED3, MACVIR, MACIVIR,
6820       RESERVED4[2], MACTFCR, RESERVED5[7], MACRFCR, RESERVED6[7], MACISR,
6821       MACIER, MACRXTXSR, RESERVED7, MACPCSR, MACRWKPFR, RESERVED8[2], MACLCSR,
6822       MACLTCR, MACLETR, MAC1USTCR, RESERVED9[12], MACVR, MACDR, RESERVED10,
6823       MACHWF0R, MACHWF1R, MACHWF2R, RESERVED11[54], MACMDIOAR, MACMDIODR,
6824       RESERVED12[2], MACARPAR, RESERVED13[59], MACA0HR, MACA0LR, MACA1HR,
6825       MACA1LR, MACA2HR, MACA2LR, MACA3HR, MACA3LR, RESERVED14[248], MMCCR,
6826       MMCRIR, MMCTIR, MMCRIMR, MMCTIMR, RESERVED15[14], MMCTSCGPR, MMCTMCGPR,
6827       RESERVED16[5], MMCTPCGR, RESERVED17[10], MMCRCRCEPR, MMCRAEPR,
6828       RESERVED18[10], MMCRUPGR, RESERVED19[9], MMCTLPIMSTR, MMCTLPITCR,
6829       MMCRLPIMSTR, MMCRLPITCR, RESERVED20[65], MACL3L4C0R, MACL4A0R,
6830       RESERVED21[2], MACL3A0R0R, MACL3A1R0R, MACL3A2R0R, MACL3A3R0R,
6831       RESERVED22[4], MACL3L4C1R, MACL4A1R, RESERVED23[2], MACL3A0R1R,
6832       MACL3A1R1R, MACL3A2R1R, MACL3A3R1R, RESERVED24[108], MACTSCR, MACSSIR,
6833       MACSTSR, MACSTNR, MACSTSUR, MACSTNUR, MACTSAR, RESERVED25, MACTSSR,
6834       RESERVED26[3], MACTTSSNR, MACTTSSSR, RESERVED27[2], MACACR, RESERVED28,
6835       MACATSNR, MACATSSR, MACTSIACR, MACTSEACR, MACTSICNR, MACTSECNR,
6836       RESERVED29[4], MACPPSCR, RESERVED30[3], MACPPSTTSR, MACPPSTTNR, MACPPSIR,
6837       MACPPSWR, RESERVED31[12], MACPOCR, MACSPI0R, MACSPI1R, MACSPI2R, MACLMIR,
6838       RESERVED32[11], MTLOMR, RESERVED33[7], MTLISR, RESERVED34[55], MTLTQOMR,
6839       MTLTQUR, MTLTQDR, RESERVED35[8], MTLQICSR, MTLRQOMR, MTLRQMPOCR, MTLRQDR,
6840       RESERVED36[177], DMAMR, DMASBMR, DMAISR, DMADSR, RESERVED37[60], DMACCR,
6841       DMACTCR, DMACRCR, RESERVED38[2], DMACTDLAR, RESERVED39, DMACRDLAR,
6842       DMACTDTPR, RESERVED40, DMACRDTPR, DMACTDRLR, DMACRDRLR, DMACIER,
6843       DMACRIWTR, DMACSFCSR, RESERVED41, DMACCATDR, RESERVED42, DMACCARDR,
6844       RESERVED43, DMACCATBR, RESERVED44, DMACCARBR, DMACSR, RESERVED45[2],
6845       DMACMFCR;
6846 };
6847 #undef ETH
6848 #define ETH \
6849   ((struct stm32h_eth *) (uintptr_t) (0x40000000UL + 0x00020000UL + 0x8000UL))
6850
6851 #undef BIT
6852 #define BIT(x) ((uint32_t) 1 << (x))
6853 #define ETH_PKT_SIZE 1540  // Max frame size
6854 #define ETH_DESC_CNT 4     // Descriptors count
6855 #define ETH_DS 4           // Descriptor size (words)
6856
6857 static volatile uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS];  // RX descriptors
6858 static volatile uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS];  // TX descriptors
6859 static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE];       // RX ethernet buffers
6860 static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE];       // TX ethernet buffers
6861 static struct mg_tcpip_if *s_ifp;                         // MIP interface
6862 enum {
6863   PHY_ADDR = 0,
6864   PHY_BCR = 0,
6865   PHY_BSR = 1,
6866   PHY_CSCR = 31
6867 };  // PHY constants
6868
6869 static uint32_t eth_read_phy(uint8_t addr, uint8_t reg) {
6870   ETH->MACMDIOAR &= (0xF << 8);
6871   ETH->MACMDIOAR |= ((uint32_t) addr << 21) | ((uint32_t) reg << 16) | 3 << 2;
6872   ETH->MACMDIOAR |= BIT(0);
6873   while (ETH->MACMDIOAR & BIT(0)) (void) 0;
6874   return ETH->MACMDIODR;
6875 }
6876
6877 static void eth_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
6878   ETH->MACMDIODR = val;
6879   ETH->MACMDIOAR &= (0xF << 8);
6880   ETH->MACMDIOAR |= ((uint32_t) addr << 21) | ((uint32_t) reg << 16) | 1 << 2;
6881   ETH->MACMDIOAR |= BIT(0);
6882   while (ETH->MACMDIOAR & BIT(0)) (void) 0;
6883 }
6884
6885 static uint32_t get_hclk(void) {
6886   struct rcc {
6887     volatile uint32_t CR, HSICFGR, CRRCR, CSICFGR, CFGR, RESERVED1, D1CFGR,
6888         D2CFGR, D3CFGR, RESERVED2, PLLCKSELR, PLLCFGR, PLL1DIVR, PLL1FRACR,
6889         PLL2DIVR, PLL2FRACR, PLL3DIVR, PLL3FRACR, RESERVED3, D1CCIPR, D2CCIP1R,
6890         D2CCIP2R, D3CCIPR, RESERVED4, CIER, CIFR, CICR, RESERVED5, BDCR, CSR,
6891         RESERVED6, AHB3RSTR, AHB1RSTR, AHB2RSTR, AHB4RSTR, APB3RSTR, APB1LRSTR,
6892         APB1HRSTR, APB2RSTR, APB4RSTR, GCR, RESERVED8, D3AMR, RESERVED11[9],
6893         RSR, AHB3ENR, AHB1ENR, AHB2ENR, AHB4ENR, APB3ENR, APB1LENR, APB1HENR,
6894         APB2ENR, APB4ENR, RESERVED12, AHB3LPENR, AHB1LPENR, AHB2LPENR,
6895         AHB4LPENR, APB3LPENR, APB1LLPENR, APB1HLPENR, APB2LPENR, APB4LPENR,
6896         RESERVED13[4];
6897   } *rcc = ((struct rcc *) (0x40000000 + 0x18020000 + 0x4400));
6898   uint32_t clk = 0, hsi = 64000000 /* 64 MHz */, hse = 8000000 /* 8MHz */,
6899            csi = 4000000 /* 4MHz */;
6900   unsigned int sel = (rcc->CFGR & (7 << 3)) >> 3;
6901
6902   if (sel == 1) {
6903     clk = csi;
6904   } else if (sel == 2) {
6905     clk = hse;
6906   } else if (sel == 3) {
6907     uint32_t vco, m, n, p;
6908     unsigned int src = (rcc->PLLCKSELR & (3 << 0)) >> 0;
6909     m = ((rcc->PLLCKSELR & (0x3F << 4)) >> 4);
6910     n = ((rcc->PLL1DIVR & (0x1FF << 0)) >> 0) + 1 +
6911         ((rcc->PLLCFGR & BIT(0)) ? 1 : 0);  // round-up in fractional mode
6912     p = ((rcc->PLL1DIVR & (0x7F << 9)) >> 9) + 1;
6913     if (src == 1) {
6914       clk = csi;
6915     } else if (src == 2) {
6916       clk = hse;
6917     } else {
6918       clk = hsi;
6919       clk >>= ((rcc->CR & 3) >> 3);
6920     }
6921     vco = (uint32_t) ((uint64_t) clk * n / m);
6922     clk = vco / p;
6923   } else {
6924     clk = hsi;
6925     clk >>= ((rcc->CR & 3) >> 3);
6926   }
6927   const uint8_t cptab[12] = {1, 2, 3, 4, 6, 7, 8, 9};  // log2(div)
6928   uint32_t d1cpre = (rcc->D1CFGR & (0x0F << 8)) >> 8;
6929   if (d1cpre >= 8) clk >>= cptab[d1cpre - 8];
6930   MG_DEBUG(("D1 CLK: %u", clk));
6931   uint32_t hpre = (rcc->D1CFGR & (0x0F << 0)) >> 0;
6932   if (hpre < 8) return clk;
6933   return ((uint32_t) clk) >> cptab[hpre - 8];
6934 }
6935
6936 //  Guess CR from AHB1 clock. MDC clock is generated from the ETH peripheral
6937 //  clock (AHB1); as per 802.3, it must not exceed 2. As the AHB clock can
6938 //  be derived from HSI or CSI (internal RC) clocks, and those can go above
6939 //  specs, the datasheets specify a range of frequencies and activate one of a
6940 //  series of dividers to keep the MDC clock safely below 2.5MHz. We guess a
6941 //  divider setting based on HCLK with some drift. If the user uses a different
6942 //  clock from our defaults, needs to set the macros on top. Valid for
6943 //  STM32H74xxx/75xxx (58.11.4)(4.5% worst case drift)(CSI clock has a 7.5 %
6944 //  worst case drift @ max temp)
6945 static int guess_mdc_cr(void) {
6946   const uint8_t crs[] = {2, 3, 0, 1, 4, 5};  // ETH->MACMDIOAR::CR values
6947   const uint8_t div[] = {16, 26, 42, 62, 102, 124};  // Respective HCLK dividers
6948   uint32_t hclk = get_hclk();                        // Guess system HCLK
6949   int result = -1;                                   // Invalid CR value
6950   for (int i = 0; i < 6; i++) {
6951     if (hclk / div[i] <= 2375000UL /* 2.5MHz - 5% */) {
6952       result = crs[i];
6953       break;
6954     }
6955   }
6956   if (result < 0) MG_ERROR(("HCLK too high"));
6957   MG_DEBUG(("HCLK: %u, CR: %d", hclk, result));
6958   return result;
6959 }
6960
6961 static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) {
6962   struct mg_tcpip_driver_stm32h_data *d =
6963       (struct mg_tcpip_driver_stm32h_data *) ifp->driver_data;
6964   s_ifp = ifp;
6965
6966   // Init RX descriptors
6967   for (int i = 0; i < ETH_DESC_CNT; i++) {
6968     s_rxdesc[i][0] = (uint32_t) (uintptr_t) s_rxbuf[i];  // Point to data buffer
6969     s_rxdesc[i][3] = BIT(31) | BIT(30) | BIT(24);        // OWN, IOC, BUF1V
6970   }
6971
6972   // Init TX descriptors
6973   for (int i = 0; i < ETH_DESC_CNT; i++) {
6974     s_txdesc[i][0] = (uint32_t) (uintptr_t) s_txbuf[i];  // Buf pointer
6975   }
6976
6977   ETH->DMAMR |= BIT(0);                         // Software reset
6978   while ((ETH->DMAMR & BIT(0)) != 0) (void) 0;  // Wait until done
6979
6980   // Set MDC clock divider. If user told us the value, use it. Otherwise, guess
6981   int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
6982   ETH->MACMDIOAR = ((uint32_t) cr & 0xF) << 8;
6983
6984   // NOTE(scaprile): We do not use timing facilities so the DMA engine does not
6985   // re-write buffer address
6986   ETH->DMAMR = 0 << 16;     // use interrupt mode 0 (58.8.1) (reset value)
6987   ETH->DMASBMR |= BIT(12);  // AAL NOTE(scaprile): is this actually needed
6988   ETH->MACIER = 0;        // Do not enable additional irq sources (reset value)
6989   ETH->MACTFCR = BIT(7);  // Disable zero-quanta pause
6990   // ETH->MACPFR = BIT(31);  // Receive all
6991   eth_write_phy(PHY_ADDR, PHY_BCR, BIT(15));  // Reset PHY
6992   eth_write_phy(PHY_ADDR, PHY_BCR, BIT(12));  // Set autonegotiation
6993   ETH->DMACRDLAR =
6994       (uint32_t) (uintptr_t) s_rxdesc;  // RX descriptors start address
6995   ETH->DMACRDRLR = ETH_DESC_CNT - 1;    // ring length
6996   ETH->DMACRDTPR =
6997       (uint32_t) (uintptr_t) &s_rxdesc[ETH_DESC_CNT -
6998                                        1];  // last valid descriptor address
6999   ETH->DMACTDLAR =
7000       (uint32_t) (uintptr_t) s_txdesc;  // TX descriptors start address
7001   ETH->DMACTDRLR = ETH_DESC_CNT - 1;    // ring length
7002   ETH->DMACTDTPR =
7003       (uint32_t) (uintptr_t) s_txdesc;  // first available descriptor address
7004   ETH->DMACCR = 0;  // DSL = 0 (contiguous descriptor table) (reset value)
7005   ETH->DMACIER = BIT(6) | BIT(15);  // RIE, NIE
7006   ETH->MACCR = BIT(0) | BIT(1) | BIT(13) | BIT(14) |
7007                BIT(15);     // RE, TE, Duplex, Fast, Reserved
7008   ETH->MTLTQOMR |= BIT(1);  // TSF
7009   ETH->MTLRQOMR |= BIT(5);  // RSF
7010   ETH->DMACTCR |= BIT(0);   // ST
7011   ETH->DMACRCR |= BIT(0);   // SR
7012
7013   // MAC address filtering
7014   ETH->MACA0HR = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
7015   ETH->MACA0LR = (uint32_t) (ifp->mac[3] << 24) |
7016                  ((uint32_t) ifp->mac[2] << 16) |
7017                  ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0];
7018   return true;
7019 }
7020
7021 static uint32_t s_txno;
7022 static size_t mg_tcpip_driver_stm32h_tx(const void *buf, size_t len,
7023                                         struct mg_tcpip_if *ifp) {
7024   if (len > sizeof(s_txbuf[s_txno])) {
7025     MG_ERROR(("Frame too big, %ld", (long) len));
7026     len = 0;  // Frame is too big
7027   } else if ((s_txdesc[s_txno][3] & BIT(31))) {
7028     MG_ERROR(("No free descriptors: %u %08X %08X %08X", s_txno,
7029               s_txdesc[s_txno][3], ETH->DMACSR, ETH->DMACTCR));
7030     for (int i = 0; i < ETH_DESC_CNT; i++) MG_ERROR(("%08X", s_txdesc[i][3]));
7031     len = 0;  // All descriptors are busy, fail
7032   } else {
7033     memcpy(s_txbuf[s_txno], buf, len);        // Copy data
7034     s_txdesc[s_txno][2] = (uint32_t) len;     // Set data len
7035     s_txdesc[s_txno][3] = BIT(28) | BIT(29);  // FD, LD
7036     s_txdesc[s_txno][3] |= BIT(31);           // Set OWN bit - let DMA take over
7037     if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
7038   }
7039   ETH->DMACSR |= BIT(2) | BIT(1);  // Clear any prior TBU, TPS
7040   ETH->DMACTDTPR = (uint32_t) (uintptr_t) &s_txdesc[s_txno];  // and resume
7041   return len;
7042   (void) ifp;
7043 }
7044
7045 static bool mg_tcpip_driver_stm32h_up(struct mg_tcpip_if *ifp) {
7046   uint32_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR);
7047   bool up = bsr & BIT(2) ? 1 : 0;
7048   if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) {  // link state just went up
7049     uint32_t scsr = eth_read_phy(PHY_ADDR, PHY_CSCR);
7050     uint32_t maccr = ETH->MACCR | BIT(14) | BIT(13);  // 100M, Full-duplex
7051     if ((scsr & BIT(3)) == 0) maccr &= ~BIT(14);      // 10M
7052     if ((scsr & BIT(4)) == 0) maccr &= ~BIT(13);      // Half-duplex
7053     ETH->MACCR = maccr;  // IRQ handler does not fiddle with this register
7054     MG_DEBUG(("Link is %uM %s-duplex", maccr & BIT(14) ? 100 : 10,
7055               maccr & BIT(13) ? "full" : "half"));
7056   }
7057   return up;
7058 }
7059
7060 void ETH_IRQHandler(void);
7061 static uint32_t s_rxno;
7062 void ETH_IRQHandler(void) {
7063   if (ETH->DMACSR & BIT(6)) {            // Frame received, loop
7064     ETH->DMACSR = BIT(15) | BIT(6);      // Clear flag
7065     for (uint32_t i = 0; i < 10; i++) {  // read as they arrive but not forever
7066       if (s_rxdesc[s_rxno][3] & BIT(31)) break;  // exit when done
7067       if (((s_rxdesc[s_rxno][3] & (BIT(28) | BIT(29))) ==
7068            (BIT(28) | BIT(29))) &&
7069           !(s_rxdesc[s_rxno][3] & BIT(15))) {  // skip partial/errored frames
7070         uint32_t len = s_rxdesc[s_rxno][3] & (BIT(15) - 1);
7071         // MG_DEBUG(("%lx %lu %lx %08lx", s_rxno, len, s_rxdesc[s_rxno][3],
7072         // ETH->DMACSR));
7073         mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
7074       }
7075       s_rxdesc[s_rxno][3] = BIT(31) | BIT(30) | BIT(24);  // OWN, IOC, BUF1V
7076       if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
7077     }
7078   }
7079   ETH->DMACSR = BIT(7) | BIT(8);  // Clear possible RBU RPS while processing
7080   ETH->DMACRDTPR =
7081       (uint32_t) (uintptr_t) &s_rxdesc[ETH_DESC_CNT - 1];  // and resume RX
7082 }
7083
7084 struct mg_tcpip_driver mg_tcpip_driver_stm32h = {
7085     mg_tcpip_driver_stm32h_init, mg_tcpip_driver_stm32h_tx, NULL,
7086     mg_tcpip_driver_stm32h_up};
7087 #endif
7088
7089 #ifdef MG_ENABLE_LINES
7090 #line 1 "src/tcpip/driver_tm4c.c"
7091 #endif
7092
7093
7094 #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_TM4C) && MG_ENABLE_DRIVER_TM4C
7095 struct tm4c_emac {
7096   volatile uint32_t EMACCFG, EMACFRAMEFLTR, EMACHASHTBLH, EMACHASHTBLL,
7097       EMACMIIADDR, EMACMIIDATA, EMACFLOWCTL, EMACVLANTG, RESERVED0, EMACSTATUS,
7098       EMACRWUFF, EMACPMTCTLSTAT, RESERVED1[2], EMACRIS, EMACIM, EMACADDR0H,
7099       EMACADDR0L, EMACADDR1H, EMACADDR1L, EMACADDR2H, EMACADDR2L, EMACADDR3H,
7100       EMACADDR3L, RESERVED2[31], EMACWDOGTO, RESERVED3[8], EMACMMCCTRL,
7101       EMACMMCRXRIS, EMACMMCTXRIS, EMACMMCRXIM, EMACMMCTXIM, RESERVED4,
7102       EMACTXCNTGB, RESERVED5[12], EMACTXCNTSCOL, EMACTXCNTMCOL, RESERVED6[4],
7103       EMACTXOCTCNTG, RESERVED7[6], EMACRXCNTGB, RESERVED8[4], EMACRXCNTCRCERR,
7104       EMACRXCNTALGNERR, RESERVED9[10], EMACRXCNTGUNI, RESERVED10[239],
7105       EMACVLNINCREP, EMACVLANHASH, RESERVED11[93], EMACTIMSTCTRL, EMACSUBSECINC,
7106       EMACTIMSEC, EMACTIMNANO, EMACTIMSECU, EMACTIMNANOU, EMACTIMADD,
7107       EMACTARGSEC, EMACTARGNANO, EMACHWORDSEC, EMACTIMSTAT, EMACPPSCTRL,
7108       RESERVED12[12], EMACPPS0INTVL, EMACPPS0WIDTH, RESERVED13[294],
7109       EMACDMABUSMOD, EMACTXPOLLD, EMACRXPOLLD, EMACRXDLADDR, EMACTXDLADDR,
7110       EMACDMARIS, EMACDMAOPMODE, EMACDMAIM, EMACMFBOC, EMACRXINTWDT,
7111       RESERVED14[8], EMACHOSTXDESC, EMACHOSRXDESC, EMACHOSTXBA, EMACHOSRXBA,
7112       RESERVED15[218], EMACPP, EMACPC, EMACCC, RESERVED16, EMACEPHYRIS,
7113       EMACEPHYIM, EMACEPHYIMSC;
7114 };
7115 #undef EMAC
7116 #define EMAC ((struct tm4c_emac *) (uintptr_t) 0x400EC000)
7117
7118 #undef BIT
7119 #define BIT(x) ((uint32_t) 1 << (x))
7120 #define ETH_PKT_SIZE 1540  // Max frame size
7121 #define ETH_DESC_CNT 4     // Descriptors count
7122 #define ETH_DS 4           // Descriptor size (words)
7123
7124 static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS];      // RX descriptors
7125 static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS];      // TX descriptors
7126 static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE];  // RX ethernet buffers
7127 static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE];  // TX ethernet buffers
7128 static struct mg_tcpip_if *s_ifp;                    // MIP interface
7129 enum {
7130   EPHY_ADDR = 0,
7131   EPHYBMCR = 0,
7132   EPHYBMSR = 1,
7133   EPHYSTS = 16
7134 };  // PHY constants
7135
7136 static inline void tm4cspin(volatile uint32_t count) {
7137   while (count--) (void) 0;
7138 }
7139
7140 static uint32_t emac_read_phy(uint8_t addr, uint8_t reg) {
7141   EMAC->EMACMIIADDR &= (0xf << 2);
7142   EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6);
7143   EMAC->EMACMIIADDR |= BIT(0);
7144   while (EMAC->EMACMIIADDR & BIT(0)) tm4cspin(1);
7145   return EMAC->EMACMIIDATA;
7146 }
7147
7148 static void emac_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
7149   EMAC->EMACMIIDATA = val;
7150   EMAC->EMACMIIADDR &= (0xf << 2);
7151   EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | BIT(1);
7152   EMAC->EMACMIIADDR |= BIT(0);
7153   while (EMAC->EMACMIIADDR & BIT(0)) tm4cspin(1);
7154 }
7155
7156 static uint32_t get_sysclk(void) {
7157   struct sysctl {
7158     volatile uint32_t DONTCARE0[44], RSCLKCFG, DONTCARE1[43], PLLFREQ0,
7159         PLLFREQ1;
7160   } *sysctl = (struct sysctl *) 0x400FE000;
7161   uint32_t clk = 0, piosc = 16000000 /* 16 MHz */, mosc = 25000000 /* 25MHz */;
7162   if (sysctl->RSCLKCFG & (1 << 28)) {  // USEPLL
7163     uint32_t fin, vco, mdiv, n, q, psysdiv;
7164     uint32_t pllsrc = (sysctl->RSCLKCFG & (0xf << 24)) >> 24;
7165     if (pllsrc == 0) {
7166       clk = piosc;
7167     } else if (pllsrc == 3) {
7168       clk = mosc;
7169     } else {
7170       MG_ERROR(("Unsupported clock source"));
7171     }
7172     q = (sysctl->PLLFREQ1 & (0x1f << 8)) >> 8;
7173     n = (sysctl->PLLFREQ1 & (0x1f << 0)) >> 0;
7174     fin = clk / ((q + 1) * (n + 1));
7175     mdiv = (sysctl->PLLFREQ0 & (0x3ff << 0)) >>
7176            0;  // mint + (mfrac / 1024); MFRAC not supported
7177     psysdiv = (sysctl->RSCLKCFG & (0x3f << 0)) >> 0;
7178     vco = (uint32_t) ((uint64_t) fin * mdiv);
7179     return vco / (psysdiv + 1);
7180   }
7181   uint32_t oscsrc = (sysctl->RSCLKCFG & (0xf << 20)) >> 20;
7182   if (oscsrc == 0) {
7183     clk = piosc;
7184   } else if (oscsrc == 3) {
7185     clk = mosc;
7186   } else {
7187     MG_ERROR(("Unsupported clock source"));
7188   }
7189   uint32_t osysdiv = (sysctl->RSCLKCFG & (0xf << 16)) >> 16;
7190   return clk / (osysdiv + 1);
7191 }
7192
7193 //  Guess CR from SYSCLK. MDC clock is generated from SYSCLK (AHB); as per
7194 //  802.3, it must not exceed 2.5MHz (also 20.4.2.6) As the AHB clock can be
7195 //  derived from the PIOSC (internal RC), and it can go above  specs, the
7196 //  datasheets specify a range of frequencies and activate one of a series of
7197 //  dividers to keep the MDC clock safely below 2.5MHz. We guess a divider
7198 //  setting based on SYSCLK with a +5% drift. If the user uses a different clock
7199 //  from our defaults, needs to set the macros on top Valid for TM4C129x (20.7)
7200 //  (4.5% worst case drift)
7201 // The PHY receives the main oscillator (MOSC) (20.3.1)
7202 static int guess_mdc_cr(void) {
7203   uint8_t crs[] = {2, 3, 0, 1};      // EMAC->MACMIIAR::CR values
7204   uint8_t div[] = {16, 26, 42, 62};  // Respective HCLK dividers
7205   uint32_t sysclk = get_sysclk();    // Guess system SYSCLK
7206   int result = -1;                   // Invalid CR value
7207   if (sysclk < 25000000) {
7208     MG_ERROR(("SYSCLK too low"));
7209   } else {
7210     for (int i = 0; i < 4; i++) {
7211       if (sysclk / div[i] <= 2375000UL /* 2.5MHz - 5% */) {
7212         result = crs[i];
7213         break;
7214       }
7215     }
7216     if (result < 0) MG_ERROR(("SYSCLK too high"));
7217   }
7218   MG_DEBUG(("SYSCLK: %u, CR: %d", sysclk, result));
7219   return result;
7220 }
7221
7222 static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
7223   struct mg_tcpip_driver_tm4c_data *d =
7224       (struct mg_tcpip_driver_tm4c_data *) ifp->driver_data;
7225   s_ifp = ifp;
7226
7227   // Init RX descriptors
7228   for (int i = 0; i < ETH_DESC_CNT; i++) {
7229     s_rxdesc[i][0] = BIT(31);                            // Own
7230     s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | BIT(14);       // 2nd address chained
7231     s_rxdesc[i][2] = (uint32_t) (uintptr_t) s_rxbuf[i];  // Point to data buffer
7232     s_rxdesc[i][3] =
7233         (uint32_t) (uintptr_t) s_rxdesc[(i + 1) % ETH_DESC_CNT];  // Chain
7234     // MG_DEBUG(("%d %p", i, s_rxdesc[i]));
7235   }
7236
7237   // Init TX descriptors
7238   for (int i = 0; i < ETH_DESC_CNT; i++) {
7239     s_txdesc[i][2] = (uint32_t) (uintptr_t) s_txbuf[i];  // Buf pointer
7240     s_txdesc[i][3] =
7241         (uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT];  // Chain
7242   }
7243
7244   EMAC->EMACDMABUSMOD |= BIT(0);                            // Software reset
7245   while ((EMAC->EMACDMABUSMOD & BIT(0)) != 0) tm4cspin(1);  // Wait until done
7246
7247   // Set MDC clock divider. If user told us the value, use it. Otherwise, guess
7248   int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
7249   EMAC->EMACMIIADDR = ((uint32_t) cr & 0xf) << 2;
7250
7251   // NOTE(cpq): we do not use extended descriptor bit 7, and do not use
7252   // hardware checksum. Therefore, descriptor size is 4, not 8
7253   // EMAC->EMACDMABUSMOD = BIT(13) | BIT(16) | BIT(22) | BIT(23) | BIT(25);
7254   EMAC->EMACIM = BIT(3) | BIT(9);  // Mask timestamp & PMT IT
7255   EMAC->EMACFLOWCTL = BIT(7);      // Disable zero-quanta pause
7256   // EMAC->EMACFRAMEFLTR = BIT(31);   // Receive all
7257   // EMAC->EMACPC defaults to internal PHY (EPHY) in MMI mode
7258   emac_write_phy(EPHY_ADDR, EPHYBMCR, BIT(15));  // Reset internal PHY (EPHY)
7259   emac_write_phy(EPHY_ADDR, EPHYBMCR, BIT(12));  // Set autonegotiation
7260   EMAC->EMACRXDLADDR = (uint32_t) (uintptr_t) s_rxdesc;  // RX descriptors
7261   EMAC->EMACTXDLADDR = (uint32_t) (uintptr_t) s_txdesc;  // TX descriptors
7262   EMAC->EMACDMAIM = BIT(6) | BIT(16);                    // RIE, NIE
7263   EMAC->EMACCFG = BIT(2) | BIT(3) | BIT(11) | BIT(14);   // RE, TE, Duplex, Fast
7264   EMAC->EMACDMAOPMODE =
7265       BIT(1) | BIT(13) | BIT(21) | BIT(25);  // SR, ST, TSF, RSF
7266   EMAC->EMACADDR0H = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
7267   EMAC->EMACADDR0L = (uint32_t) (ifp->mac[3] << 24) |
7268                      ((uint32_t) ifp->mac[2] << 16) |
7269                      ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0];
7270   // NOTE(scaprile) There are 3 additional slots for filtering, disabled by
7271   // default. This also applies to the STM32 driver (at least for F7)
7272   return true;
7273 }
7274
7275 static uint32_t s_txno;
7276 static size_t mg_tcpip_driver_tm4c_tx(const void *buf, size_t len,
7277                                       struct mg_tcpip_if *ifp) {
7278   if (len > sizeof(s_txbuf[s_txno])) {
7279     MG_ERROR(("Frame too big, %ld", (long) len));
7280     len = 0;  // fail
7281   } else if ((s_txdesc[s_txno][0] & BIT(31))) {
7282     MG_ERROR(("No descriptors available"));
7283     // printf("D0 %lx SR %lx\n", (long) s_txdesc[0][0], (long)
7284     // EMAC->EMACDMARIS);
7285     len = 0;  // fail
7286   } else {
7287     memcpy(s_txbuf[s_txno], buf, len);     // Copy data
7288     s_txdesc[s_txno][1] = (uint32_t) len;  // Set data len
7289     s_txdesc[s_txno][0] =
7290         BIT(20) | BIT(28) | BIT(29) | BIT(30);  // Chain,FS,LS,IC
7291     s_txdesc[s_txno][0] |= BIT(31);  // Set OWN bit - let DMA take over
7292     if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
7293   }
7294   EMAC->EMACDMARIS = BIT(2) | BIT(5);  // Clear any prior TU/UNF
7295   EMAC->EMACTXPOLLD = 0;               // and resume
7296   return len;
7297   (void) ifp;
7298 }
7299
7300 static bool mg_tcpip_driver_tm4c_up(struct mg_tcpip_if *ifp) {
7301   uint32_t bmsr = emac_read_phy(EPHY_ADDR, EPHYBMSR);
7302   bool up = (bmsr & BIT(2)) ? 1 : 0;
7303   if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) {  // link state just went up
7304     uint32_t sts = emac_read_phy(EPHY_ADDR, EPHYSTS);
7305     uint32_t emaccfg = EMAC->EMACCFG | BIT(14) | BIT(11);  // 100M, Full-duplex
7306     if (sts & BIT(1)) emaccfg &= ~BIT(14);                 // 10M
7307     if ((sts & BIT(2)) == 0) emaccfg &= ~BIT(11);          // Half-duplex
7308     EMAC->EMACCFG = emaccfg;  // IRQ handler does not fiddle with this register
7309     MG_DEBUG(("Link is %uM %s-duplex", emaccfg & BIT(14) ? 100 : 10,
7310               emaccfg & BIT(11) ? "full" : "half"));
7311   }
7312   return up;
7313 }
7314
7315 void EMAC0_IRQHandler(void);
7316 static uint32_t s_rxno;
7317 void EMAC0_IRQHandler(void) {
7318   if (EMAC->EMACDMARIS & BIT(6)) {        // Frame received, loop
7319     EMAC->EMACDMARIS = BIT(16) | BIT(6);  // Clear flag
7320     for (uint32_t i = 0; i < 10; i++) {   // read as they arrive but not forever
7321       if (s_rxdesc[s_rxno][0] & BIT(31)) break;  // exit when done
7322       if (((s_rxdesc[s_rxno][0] & (BIT(8) | BIT(9))) == (BIT(8) | BIT(9))) &&
7323           !(s_rxdesc[s_rxno][0] & BIT(15))) {  // skip partial/errored frames
7324         uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (BIT(14) - 1));
7325         //  printf("%lx %lu %lx %.8lx\n", s_rxno, len, s_rxdesc[s_rxno][0],
7326         //  EMAC->EMACDMARIS);
7327         mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
7328       }
7329       s_rxdesc[s_rxno][0] = BIT(31);
7330       if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
7331     }
7332   }
7333   EMAC->EMACDMARIS = BIT(7);  // Clear possible RU while processing
7334   EMAC->EMACRXPOLLD = 0;      // and resume RX
7335 }
7336
7337 struct mg_tcpip_driver mg_tcpip_driver_tm4c = {mg_tcpip_driver_tm4c_init,
7338                                                mg_tcpip_driver_tm4c_tx, NULL,
7339                                                mg_tcpip_driver_tm4c_up};
7340 #endif
7341
7342 #ifdef MG_ENABLE_LINES
7343 #line 1 "src/tcpip/driver_w5500.c"
7344 #endif
7345
7346
7347 #if MG_ENABLE_TCPIP
7348
7349 enum { W5500_CR = 0, W5500_S0 = 1, W5500_TX0 = 2, W5500_RX0 = 3 };
7350
7351 static void w5500_txn(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr, bool wr,
7352                       void *buf, size_t len) {
7353   uint8_t *p = (uint8_t *) buf;
7354   uint8_t cmd[] = {(uint8_t) (addr >> 8), (uint8_t) (addr & 255),
7355                    (uint8_t) ((block << 3) | (wr ? 4 : 0))};
7356   s->begin(s->spi);
7357   for (size_t i = 0; i < sizeof(cmd); i++) s->txn(s->spi, cmd[i]);
7358   for (size_t i = 0; i < len; i++) {
7359     uint8_t r = s->txn(s->spi, p[i]);
7360     if (!wr) p[i] = r;
7361   }
7362   s->end(s->spi);
7363 }
7364
7365 // clang-format off
7366 static  void w5500_wn(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr, void *buf, size_t len) { w5500_txn(s, block, addr, true, buf, len); }
7367 static  void w5500_w1(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr, uint8_t val) { w5500_wn(s, block, addr, &val, 1); }
7368 static  void w5500_w2(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr, uint16_t val) { uint8_t buf[2] = {(uint8_t) (val >> 8), (uint8_t) (val & 255)}; w5500_wn(s, block, addr, buf, sizeof(buf)); }
7369 static  void w5500_rn(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr, void *buf, size_t len) { w5500_txn(s, block, addr, false, buf, len); }
7370 static  uint8_t w5500_r1(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr) { uint8_t r = 0; w5500_rn(s, block, addr, &r, 1); return r; }
7371 static  uint16_t w5500_r2(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr) { uint8_t buf[2] = {0, 0}; w5500_rn(s, block, addr, buf, sizeof(buf)); return (uint16_t) ((buf[0] << 8) | buf[1]); }
7372 // clang-format on
7373
7374 static size_t w5500_rx(void *buf, size_t buflen, struct mg_tcpip_if *ifp) {
7375   struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data;
7376   uint16_t r = 0, n = 0, len = (uint16_t) buflen, n2;     // Read recv len
7377   while ((n2 = w5500_r2(s, W5500_S0, 0x26)) > n) n = n2;  // Until it is stable
7378   // printf("RSR: %d\n", (int) n);
7379   if (n > 0) {
7380     uint16_t ptr = w5500_r2(s, W5500_S0, 0x28);  // Get read pointer
7381     n = w5500_r2(s, W5500_RX0, ptr);             // Read frame length
7382     if (n <= len + 2 && n > 1) {
7383       r = (uint16_t) (n - 2);
7384       w5500_rn(s, W5500_RX0, (uint16_t) (ptr + 2), buf, r);
7385     }
7386     w5500_w2(s, W5500_S0, 0x28, (uint16_t) (ptr + n));  // Advance read pointer
7387     w5500_w1(s, W5500_S0, 1, 0x40);                     // Sock0 CR -> RECV
7388     // printf("  RX_RD: tot=%u n=%u r=%u\n", n2, n, r);
7389   }
7390   return r;
7391 }
7392
7393 static size_t w5500_tx(const void *buf, size_t buflen, struct mg_tcpip_if *ifp) {
7394   struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data;
7395   uint16_t n = 0, len = (uint16_t) buflen;
7396   while (n < len) n = w5500_r2(s, W5500_S0, 0x20);      // Wait for space
7397   uint16_t ptr = w5500_r2(s, W5500_S0, 0x24);           // Get write pointer
7398   w5500_wn(s, W5500_TX0, ptr, (void *) buf, len);       // Write data
7399   w5500_w2(s, W5500_S0, 0x24, (uint16_t) (ptr + len));  // Advance write pointer
7400   w5500_w1(s, W5500_S0, 1, 0x20);                       // Sock0 CR -> SEND
7401   for (int i = 0; i < 40; i++) {
7402     uint8_t ir = w5500_r1(s, W5500_S0, 2);  // Read S0 IR
7403     if (ir == 0) continue;
7404     // printf("IR %d, len=%d, free=%d, ptr %d\n", ir, (int) len, (int) n, ptr);
7405     w5500_w1(s, W5500_S0, 2, ir);  // Write S0 IR: clear it!
7406     if (ir & 8) len = 0;           // Timeout. Report error
7407     if (ir & (16 | 8)) break;      // Stop on SEND_OK or timeout
7408   }
7409   return len;
7410 }
7411
7412 static bool w5500_init(struct mg_tcpip_if *ifp) {
7413   struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data;
7414   s->end(s->spi);
7415   w5500_w1(s, W5500_CR, 0, 0x80);     // Reset chip: CR -> 0x80
7416   w5500_w1(s, W5500_CR, 0x2e, 0);     // CR PHYCFGR -> reset
7417   w5500_w1(s, W5500_CR, 0x2e, 0xf8);  // CR PHYCFGR -> set
7418   // w5500_wn(s, W5500_CR, 9, s->mac, 6);      // Set source MAC
7419   w5500_w1(s, W5500_S0, 0x1e, 16);          // Sock0 RX buf size
7420   w5500_w1(s, W5500_S0, 0x1f, 16);          // Sock0 TX buf size
7421   w5500_w1(s, W5500_S0, 0, 4);              // Sock0 MR -> MACRAW
7422   w5500_w1(s, W5500_S0, 1, 1);              // Sock0 CR -> OPEN
7423   return w5500_r1(s, W5500_S0, 3) == 0x42;  // Sock0 SR == MACRAW
7424 }
7425
7426 static bool w5500_up(struct mg_tcpip_if *ifp) {
7427   struct mg_tcpip_spi *spi = (struct mg_tcpip_spi *) ifp->driver_data;
7428   uint8_t phycfgr = w5500_r1(spi, W5500_CR, 0x2e);
7429   return phycfgr & 1;  // Bit 0 of PHYCFGR is LNK (0 - down, 1 - up)
7430 }
7431
7432 struct mg_tcpip_driver mg_tcpip_driver_w5500 = {w5500_init, w5500_tx, w5500_rx, w5500_up};
7433 #endif
7434
7435 #ifdef MG_ENABLE_LINES
7436 #line 1 "src/tcpip/tcpip.c"
7437 #endif
7438
7439
7440 #if MG_ENABLE_TCPIP
7441
7442 #define MG_EPHEMERAL_PORT_BASE 32768
7443 #define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a))))
7444
7445 #ifndef MIP_TCP_KEEPALIVE_MS
7446 #define MIP_TCP_KEEPALIVE_MS 45000  // TCP keep-alive period, ms
7447 #endif
7448
7449 #define MIP_TCP_ACK_MS 150  // Timeout for ACKing
7450
7451 struct connstate {
7452   uint32_t seq, ack;           // TCP seq/ack counters
7453   uint64_t timer;              // TCP keep-alive / ACK timer
7454   uint8_t mac[6];              // Peer MAC address
7455   uint8_t ttype;               // Timer type. 0: ack, 1: keep-alive
7456 #define MIP_TTYPE_KEEPALIVE 0  // Connection is idle for long, send keepalive
7457 #define MIP_TTYPE_ACK 1        // Peer sent us data, we have to ack it soon
7458   uint8_t tmiss;               // Number of keep-alive misses
7459   struct mg_iobuf raw;         // For TLS only. Incoming raw data
7460 };
7461
7462 #pragma pack(push, 1)
7463
7464 struct lcp {
7465   uint8_t addr, ctrl, proto[2], code, id, len[2];
7466 };
7467
7468 struct eth {
7469   uint8_t dst[6];  // Destination MAC address
7470   uint8_t src[6];  // Source MAC address
7471   uint16_t type;   // Ethernet type
7472 };
7473
7474 struct ip {
7475   uint8_t ver;    // Version
7476   uint8_t tos;    // Unused
7477   uint16_t len;   // Length
7478   uint16_t id;    // Unused
7479   uint16_t frag;  // Fragmentation
7480   uint8_t ttl;    // Time to live
7481   uint8_t proto;  // Upper level protocol
7482   uint16_t csum;  // Checksum
7483   uint32_t src;   // Source IP
7484   uint32_t dst;   // Destination IP
7485 };
7486
7487 struct ip6 {
7488   uint8_t ver;      // Version
7489   uint8_t opts[3];  // Options
7490   uint16_t len;     // Length
7491   uint8_t proto;    // Upper level protocol
7492   uint8_t ttl;      // Time to live
7493   uint8_t src[16];  // Source IP
7494   uint8_t dst[16];  // Destination IP
7495 };
7496
7497 struct icmp {
7498   uint8_t type;
7499   uint8_t code;
7500   uint16_t csum;
7501 };
7502
7503 struct arp {
7504   uint16_t fmt;    // Format of hardware address
7505   uint16_t pro;    // Format of protocol address
7506   uint8_t hlen;    // Length of hardware address
7507   uint8_t plen;    // Length of protocol address
7508   uint16_t op;     // Operation
7509   uint8_t sha[6];  // Sender hardware address
7510   uint32_t spa;    // Sender protocol address
7511   uint8_t tha[6];  // Target hardware address
7512   uint32_t tpa;    // Target protocol address
7513 };
7514
7515 struct tcp {
7516   uint16_t sport;  // Source port
7517   uint16_t dport;  // Destination port
7518   uint32_t seq;    // Sequence number
7519   uint32_t ack;    // Acknowledgement number
7520   uint8_t off;     // Data offset
7521   uint8_t flags;   // TCP flags
7522 #define TH_FIN 0x01
7523 #define TH_SYN 0x02
7524 #define TH_RST 0x04
7525 #define TH_PUSH 0x08
7526 #define TH_ACK 0x10
7527 #define TH_URG 0x20
7528 #define TH_ECE 0x40
7529 #define TH_CWR 0x80
7530   uint16_t win;   // Window
7531   uint16_t csum;  // Checksum
7532   uint16_t urp;   // Urgent pointer
7533 };
7534
7535 struct udp {
7536   uint16_t sport;  // Source port
7537   uint16_t dport;  // Destination port
7538   uint16_t len;    // UDP length
7539   uint16_t csum;   // UDP checksum
7540 };
7541
7542 struct dhcp {
7543   uint8_t op, htype, hlen, hops;
7544   uint32_t xid;
7545   uint16_t secs, flags;
7546   uint32_t ciaddr, yiaddr, siaddr, giaddr;
7547   uint8_t hwaddr[208];
7548   uint32_t magic;
7549   uint8_t options[32];
7550 };
7551
7552 #pragma pack(pop)
7553
7554 struct pkt {
7555   struct mg_str raw;  // Raw packet data
7556   struct mg_str pay;  // Payload data
7557   struct eth *eth;
7558   struct llc *llc;
7559   struct arp *arp;
7560   struct ip *ip;
7561   struct ip6 *ip6;
7562   struct icmp *icmp;
7563   struct tcp *tcp;
7564   struct udp *udp;
7565   struct dhcp *dhcp;
7566 };
7567
7568 static void mkpay(struct pkt *pkt, void *p) {
7569   pkt->pay =
7570       mg_str_n((char *) p, (size_t) (&pkt->raw.ptr[pkt->raw.len] - (char *) p));
7571 }
7572
7573 static uint32_t csumup(uint32_t sum, const void *buf, size_t len) {
7574   const uint8_t *p = (const uint8_t *) buf;
7575   for (size_t i = 0; i < len; i++) sum += i & 1 ? p[i] : (uint32_t) (p[i] << 8);
7576   return sum;
7577 }
7578
7579 static uint16_t csumfin(uint32_t sum) {
7580   while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
7581   return mg_htons(~sum & 0xffff);
7582 }
7583
7584 static uint16_t ipcsum(const void *buf, size_t len) {
7585   uint32_t sum = csumup(0, buf, len);
7586   return csumfin(sum);
7587 }
7588
7589 static size_t ether_output(struct mg_tcpip_if *ifp, size_t len) {
7590   // size_t min = 64;  // Pad short frames to 64 bytes (minimum Ethernet size)
7591   // if (len < min) memset(ifp->tx.ptr + len, 0, min - len), len = min;
7592   // mg_hexdump(ifp->tx.ptr, len);
7593   size_t n = ifp->driver->tx(ifp->tx.ptr, len, ifp);
7594   if (n == len) ifp->nsent++;
7595   return n;
7596 }
7597
7598 static void arp_ask(struct mg_tcpip_if *ifp, uint32_t ip) {
7599   struct eth *eth = (struct eth *) ifp->tx.ptr;
7600   struct arp *arp = (struct arp *) (eth + 1);
7601   memset(eth->dst, 255, sizeof(eth->dst));
7602   memcpy(eth->src, ifp->mac, sizeof(eth->src));
7603   eth->type = mg_htons(0x806);
7604   memset(arp, 0, sizeof(*arp));
7605   arp->fmt = mg_htons(1), arp->pro = mg_htons(0x800), arp->hlen = 6,
7606   arp->plen = 4;
7607   arp->op = mg_htons(1), arp->tpa = ip, arp->spa = ifp->ip;
7608   memcpy(arp->sha, ifp->mac, sizeof(arp->sha));
7609   ether_output(ifp, PDIFF(eth, arp + 1));
7610 }
7611
7612 static void onstatechange(struct mg_tcpip_if *ifp) {
7613   if (ifp->state == MG_TCPIP_STATE_READY) {
7614     MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip));
7615     MG_INFO(("       GW: %M", mg_print_ip4, &ifp->gw));
7616     if (ifp->lease_expire > ifp->now) {
7617       MG_INFO(
7618           ("       Lease: %lld sec", (ifp->lease_expire - ifp->now) / 1000));
7619     }
7620     arp_ask(ifp, ifp->gw);
7621   } else if (ifp->state == MG_TCPIP_STATE_UP) {
7622     MG_ERROR(("Link up"));
7623     srand((unsigned int) mg_millis());
7624   } else if (ifp->state == MG_TCPIP_STATE_DOWN) {
7625     MG_ERROR(("Link down"));
7626   }
7627 }
7628
7629 static struct ip *tx_ip(struct mg_tcpip_if *ifp, uint8_t *mac_dst,
7630                         uint8_t proto, uint32_t ip_src, uint32_t ip_dst,
7631                         size_t plen) {
7632   struct eth *eth = (struct eth *) ifp->tx.ptr;
7633   struct ip *ip = (struct ip *) (eth + 1);
7634   memcpy(eth->dst, mac_dst, sizeof(eth->dst));
7635   memcpy(eth->src, ifp->mac, sizeof(eth->src));  // Use our MAC
7636   eth->type = mg_htons(0x800);
7637   memset(ip, 0, sizeof(*ip));
7638   ip->ver = 0x45;   // Version 4, header length 5 words
7639   ip->frag = 0x40;  // Don't fragment
7640   ip->len = mg_htons((uint16_t) (sizeof(*ip) + plen));
7641   ip->ttl = 64;
7642   ip->proto = proto;
7643   ip->src = ip_src;
7644   ip->dst = ip_dst;
7645   ip->csum = ipcsum(ip, sizeof(*ip));
7646   return ip;
7647 }
7648
7649 static void tx_udp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src,
7650                    uint16_t sport, uint32_t ip_dst, uint16_t dport,
7651                    const void *buf, size_t len) {
7652   struct ip *ip =
7653       tx_ip(ifp, mac_dst, 17, ip_src, ip_dst, len + sizeof(struct udp));
7654   struct udp *udp = (struct udp *) (ip + 1);
7655   // MG_DEBUG(("UDP XX LEN %d %d", (int) len, (int) ifp->tx.len));
7656   udp->sport = sport;
7657   udp->dport = dport;
7658   udp->len = mg_htons((uint16_t) (sizeof(*udp) + len));
7659   udp->csum = 0;
7660   uint32_t cs = csumup(0, udp, sizeof(*udp));
7661   cs = csumup(cs, buf, len);
7662   cs = csumup(cs, &ip->src, sizeof(ip->src));
7663   cs = csumup(cs, &ip->dst, sizeof(ip->dst));
7664   cs += (uint32_t) (ip->proto + sizeof(*udp) + len);
7665   udp->csum = csumfin(cs);
7666   memmove(udp + 1, buf, len);
7667   // MG_DEBUG(("UDP LEN %d %d", (int) len, (int) ifp->frame_len));
7668   ether_output(ifp, sizeof(struct eth) + sizeof(*ip) + sizeof(*udp) + len);
7669 }
7670
7671 static void tx_dhcp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src,
7672                     uint32_t ip_dst, uint8_t *opts, size_t optslen) {
7673   struct dhcp dhcp = {1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {0}};
7674   dhcp.magic = mg_htonl(0x63825363);
7675   memcpy(&dhcp.hwaddr, ifp->mac, sizeof(ifp->mac));
7676   memcpy(&dhcp.xid, ifp->mac + 2, sizeof(dhcp.xid));
7677   memcpy(&dhcp.options, opts, optslen);
7678   tx_udp(ifp, mac_dst, ip_src, mg_htons(68), ip_dst, mg_htons(67), &dhcp,
7679          sizeof(dhcp));
7680 }
7681
7682 static void tx_dhcp_request(struct mg_tcpip_if *ifp, uint8_t *mac_dst,
7683                             uint32_t ip_src, uint32_t ip_dst) {
7684   uint8_t opts[] = {
7685       53, 1, 3,                 // Type: DHCP request
7686       55, 2, 1,   3,            // GW and mask
7687       12, 3, 'm', 'i', 'p',     // Host name: "mip"
7688       54, 4, 0,   0,   0,   0,  // DHCP server ID
7689       50, 4, 0,   0,   0,   0,  // Requested IP
7690       255                       // End of options
7691   };
7692   memcpy(opts + 14, &ip_dst, sizeof(ip_dst));
7693   memcpy(opts + 20, &ip_src, sizeof(ip_src));
7694   tx_dhcp(ifp, mac_dst, ip_src, ip_dst, opts, sizeof(opts));
7695 }
7696
7697 static void tx_dhcp_discover(struct mg_tcpip_if *ifp) {
7698   uint8_t mac[6] = {255, 255, 255, 255, 255, 255};
7699   uint8_t opts[] = {
7700       53, 1, 1,     // Type: DHCP discover
7701       55, 2, 1, 3,  // Parameters: ip, mask
7702       255           // End of options
7703   };
7704   tx_dhcp(ifp, mac, 0, 0xffffffff, opts, sizeof(opts));
7705   MG_DEBUG(("DHCP discover sent"));
7706 }
7707
7708 static struct mg_connection *getpeer(struct mg_mgr *mgr, struct pkt *pkt,
7709                                      bool lsn) {
7710   struct mg_connection *c = NULL;
7711   for (c = mgr->conns; c != NULL; c = c->next) {
7712     if (c->is_udp && pkt->udp && c->loc.port == pkt->udp->dport) break;
7713     if (!c->is_udp && pkt->tcp && c->loc.port == pkt->tcp->dport &&
7714         lsn == c->is_listening && (lsn || c->rem.port == pkt->tcp->sport))
7715       break;
7716   }
7717   return c;
7718 }
7719
7720 static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
7721   if (pkt->arp->op == mg_htons(1) && pkt->arp->tpa == ifp->ip) {
7722     // ARP request. Make a response, then send
7723     // MG_DEBUG(("ARP op %d %M: %M", mg_ntohs(pkt->arp->op), mg_print_ip4,
7724     //          &pkt->arp->spa, mg_print_ip4, &pkt->arp->tpa));
7725     struct eth *eth = (struct eth *) ifp->tx.ptr;
7726     struct arp *arp = (struct arp *) (eth + 1);
7727     memcpy(eth->dst, pkt->eth->src, sizeof(eth->dst));
7728     memcpy(eth->src, ifp->mac, sizeof(eth->src));
7729     eth->type = mg_htons(0x806);
7730     *arp = *pkt->arp;
7731     arp->op = mg_htons(2);
7732     memcpy(arp->tha, pkt->arp->sha, sizeof(pkt->arp->tha));
7733     memcpy(arp->sha, ifp->mac, sizeof(pkt->arp->sha));
7734     arp->tpa = pkt->arp->spa;
7735     arp->spa = ifp->ip;
7736     MG_DEBUG(("ARP: tell %M we're %M", mg_print_ip4, &arp->tpa, mg_print_ip4,
7737               &ifp->ip));
7738     ether_output(ifp, PDIFF(eth, arp + 1));
7739   } else if (pkt->arp->op == mg_htons(2)) {
7740     if (memcmp(pkt->arp->tha, ifp->mac, sizeof(pkt->arp->tha)) != 0) return;
7741     if (pkt->arp->spa == ifp->gw) {
7742       // Got response for the GW ARP request. Set ifp->gwmac
7743       memcpy(ifp->gwmac, pkt->arp->sha, sizeof(ifp->gwmac));
7744     } else {
7745       struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
7746       if (c != NULL && c->is_arplooking) {
7747         struct connstate *s = (struct connstate *) (c + 1);
7748         memcpy(s->mac, pkt->arp->sha, sizeof(s->mac));
7749         MG_DEBUG(("%lu ARP resolved %M -> %M", c->id, mg_print_ip4, &c->rem.ip,
7750                   mg_print_mac, s->mac));
7751         c->is_arplooking = 0;
7752       }
7753     }
7754   }
7755 }
7756
7757 static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
7758   // MG_DEBUG(("ICMP %d", (int) len));
7759   if (pkt->icmp->type == 8 && pkt->ip != NULL && pkt->ip->dst == ifp->ip) {
7760     size_t hlen = sizeof(struct eth) + sizeof(struct ip) + sizeof(struct icmp);
7761     size_t space = ifp->tx.len - hlen, plen = pkt->pay.len;
7762     if (plen > space) plen = space;
7763     struct ip *ip = tx_ip(ifp, pkt->eth->src, 1, ifp->ip, pkt->ip->src,
7764                           sizeof(struct icmp) + plen);
7765     struct icmp *icmp = (struct icmp *) (ip + 1);
7766     memset(icmp, 0, sizeof(*icmp));        // Set csum to 0
7767     memcpy(icmp + 1, pkt->pay.ptr, plen);  // Copy RX payload to TX
7768     icmp->csum = ipcsum(icmp, sizeof(*icmp) + plen);
7769     ether_output(ifp, hlen + plen);
7770   }
7771 }
7772
7773 static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
7774   uint32_t ip = 0, gw = 0, mask = 0;
7775   uint8_t *p = pkt->dhcp->options,
7776           *end = (uint8_t *) &pkt->raw.ptr[pkt->raw.len];
7777   if (end < (uint8_t *) (pkt->dhcp + 1)) return;
7778   while (p + 1 < end && p[0] != 255) {  // Parse options
7779     if (p[0] == 1 && p[1] == sizeof(ifp->mask) && p + 6 < end) {  // Mask
7780       memcpy(&mask, p + 2, sizeof(mask));
7781     } else if (p[0] == 3 && p[1] == sizeof(ifp->gw) && p + 6 < end) {  // GW
7782       memcpy(&gw, p + 2, sizeof(gw));
7783       ip = pkt->dhcp->yiaddr;
7784     } else if (p[0] == 51 && p[1] == 4 && p + 6 < end) {  // Lease
7785       uint32_t lease = 0;
7786       memcpy(&lease, p + 2, sizeof(lease));
7787       ifp->lease_expire = ifp->now + mg_ntohl(lease) * 1000;
7788     }
7789     p += p[1] + 2;
7790   }
7791   if (ip && mask && gw && ifp->ip == 0) {
7792     memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac));
7793     ifp->ip = ip, ifp->gw = gw, ifp->mask = mask;
7794     ifp->state = MG_TCPIP_STATE_READY;
7795     onstatechange(ifp);
7796     tx_dhcp_request(ifp, pkt->eth->src, ip, pkt->dhcp->siaddr);
7797     uint64_t rand;
7798     mg_random(&rand, sizeof(rand));
7799     srand((unsigned int) (rand + mg_millis()));
7800   }
7801 }
7802
7803 // Simple DHCP server that assigns a next IP address: ifp->ip + 1
7804 static void rx_dhcp_server(struct mg_tcpip_if *ifp, struct pkt *pkt) {
7805   uint8_t op = 0, *p = pkt->dhcp->options,
7806           *end = (uint8_t *) &pkt->raw.ptr[pkt->raw.len];
7807   if (end < (uint8_t *) (pkt->dhcp + 1)) return;
7808   // struct dhcp *req = pkt->dhcp;
7809   struct dhcp res = {2, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {0}};
7810   res.yiaddr = ifp->ip;
7811   ((uint8_t *) (&res.yiaddr))[3]++;                // Offer our IP + 1
7812   while (p + 1 < end && p[0] != 255) {             // Parse options
7813     if (p[0] == 53 && p[1] == 1 && p + 2 < end) {  // Message type
7814       op = p[2];
7815     }
7816     p += p[1] + 2;
7817   }
7818   if (op == 1 || op == 3) {         // DHCP Discover or DHCP Request
7819     uint8_t msg = op == 1 ? 2 : 5;  // Message type: DHCP OFFER or DHCP ACK
7820     uint8_t opts[] = {
7821         53, 1, msg,                 // Message type
7822         1,  4, 0,   0,   0,   0,    // Subnet mask
7823         54, 4, 0,   0,   0,   0,    // Server ID
7824         12, 3, 'm', 'i', 'p',       // Host name: "mip"
7825         51, 4, 255, 255, 255, 255,  // Lease time
7826         255                         // End of options
7827     };
7828     memcpy(&res.hwaddr, pkt->dhcp->hwaddr, 6);
7829     memcpy(opts + 5, &ifp->mask, sizeof(ifp->mask));
7830     memcpy(opts + 11, &ifp->ip, sizeof(ifp->ip));
7831     memcpy(&res.options, opts, sizeof(opts));
7832     res.magic = pkt->dhcp->magic;
7833     res.xid = pkt->dhcp->xid;
7834     // memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac));
7835     tx_udp(ifp, pkt->eth->src, ifp->ip, mg_htons(67),
7836            op == 1 ? ~0U : res.yiaddr, mg_htons(68), &res, sizeof(res));
7837   }
7838 }
7839
7840 static void rx_udp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
7841   struct mg_connection *c = getpeer(ifp->mgr, pkt, true);
7842   if (c == NULL) {
7843     // No UDP listener on this port. Should send ICMP, but keep silent.
7844   } else {
7845     c->rem.port = pkt->udp->sport;
7846     c->rem.ip = pkt->ip->src;
7847     struct connstate *s = (struct connstate *) (c + 1);
7848     memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
7849     if (c->recv.len >= MG_MAX_RECV_SIZE) {
7850       mg_error(c, "max_recv_buf_size reached");
7851     } else if (c->recv.size - c->recv.len < pkt->pay.len &&
7852                !mg_iobuf_resize(&c->recv, c->recv.len + pkt->pay.len)) {
7853       mg_error(c, "oom");
7854     } else {
7855       memcpy(&c->recv.buf[c->recv.len], pkt->pay.ptr, pkt->pay.len);
7856       c->recv.len += pkt->pay.len;
7857       mg_call(c, MG_EV_READ, &pkt->pay.len);
7858     }
7859   }
7860 }
7861
7862 static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *dst_mac, uint32_t dst_ip,
7863                      uint8_t flags, uint16_t sport, uint16_t dport,
7864                      uint32_t seq, uint32_t ack, const void *buf, size_t len) {
7865   struct ip *ip =
7866       tx_ip(ifp, dst_mac, 6, ifp->ip, dst_ip, sizeof(struct tcp) + len);
7867   struct tcp *tcp = (struct tcp *) (ip + 1);
7868   memset(tcp, 0, sizeof(*tcp));
7869   if (buf != NULL && len) memmove(tcp + 1, buf, len);
7870   tcp->sport = sport;
7871   tcp->dport = dport;
7872   tcp->seq = seq;
7873   tcp->ack = ack;
7874   tcp->flags = flags;
7875   tcp->win = mg_htons(8192);
7876   tcp->off = (uint8_t) (sizeof(*tcp) / 4 << 4);
7877   uint32_t cs = 0;
7878   uint16_t n = (uint16_t) (sizeof(*tcp) + len);
7879   uint8_t pseudo[] = {0, ip->proto, (uint8_t) (n >> 8), (uint8_t) (n & 255)};
7880   cs = csumup(cs, tcp, n);
7881   cs = csumup(cs, &ip->src, sizeof(ip->src));
7882   cs = csumup(cs, &ip->dst, sizeof(ip->dst));
7883   cs = csumup(cs, pseudo, sizeof(pseudo));
7884   tcp->csum = csumfin(cs);
7885   MG_DEBUG(("TCP %M:%hu -> %M:%hu fl %x len %u", mg_print_ip4, &ip->src,
7886             mg_ntohs(tcp->sport), mg_print_ip4, &ip->dst, mg_ntohs(tcp->dport),
7887             tcp->flags, (int) len));
7888   return ether_output(ifp, PDIFF(ifp->tx.ptr, tcp + 1) + len);
7889 }
7890
7891 static size_t tx_tcp_pkt(struct mg_tcpip_if *ifp, struct pkt *pkt,
7892                          uint8_t flags, uint32_t seq, const void *buf,
7893                          size_t len) {
7894   uint32_t delta = (pkt->tcp->flags & (TH_SYN | TH_FIN)) ? 1 : 0;
7895   return tx_tcp(ifp, pkt->eth->src, pkt->ip->src, flags, pkt->tcp->dport,
7896                 pkt->tcp->sport, seq, mg_htonl(mg_ntohl(pkt->tcp->seq) + delta),
7897                 buf, len);
7898 }
7899
7900 static void settmout(struct mg_connection *c, uint8_t type) {
7901   struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
7902   struct connstate *s = (struct connstate *) (c + 1);
7903   unsigned n = type == MIP_TTYPE_ACK ? MIP_TCP_ACK_MS : MIP_TCP_KEEPALIVE_MS;
7904   s->timer = ifp->now + n;
7905   s->ttype = type;
7906   MG_VERBOSE(("%lu %d -> %llx", c->id, type, s->timer));
7907 }
7908
7909 static struct mg_connection *accept_conn(struct mg_connection *lsn,
7910                                          struct pkt *pkt) {
7911   struct mg_connection *c = mg_alloc_conn(lsn->mgr);
7912   if (c == NULL) {
7913     MG_ERROR(("OOM"));
7914     return NULL;
7915   }
7916   struct connstate *s = (struct connstate *) (c + 1);
7917   s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq);
7918   memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
7919   settmout(c, MIP_TTYPE_KEEPALIVE);
7920   c->rem.ip = pkt->ip->src;
7921   c->rem.port = pkt->tcp->sport;
7922   MG_DEBUG(("%lu accepted %M", c->id, mg_print_ip_port, &c->rem));
7923   LIST_ADD_HEAD(struct mg_connection, &lsn->mgr->conns, c);
7924   c->is_accepted = 1;
7925   c->is_hexdumping = lsn->is_hexdumping;
7926   c->pfn = lsn->pfn;
7927   c->loc = lsn->loc;
7928   c->pfn_data = lsn->pfn_data;
7929   c->fn = lsn->fn;
7930   c->fn_data = lsn->fn_data;
7931   mg_call(c, MG_EV_OPEN, NULL);
7932   mg_call(c, MG_EV_ACCEPT, NULL);
7933   return c;
7934 }
7935
7936 long mg_io_send(struct mg_connection *c, const void *buf, size_t len) {
7937   struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
7938   struct connstate *s = (struct connstate *) (c + 1);
7939   if (c->is_udp) {
7940     size_t max_headers_len = 14 + 24 /* max IP */ + 8 /* UDP */;
7941     if (len + max_headers_len > ifp->tx.len) len = ifp->tx.len - max_headers_len;
7942     tx_udp(ifp, s->mac, ifp->ip, c->loc.port, c->rem.ip, c->rem.port, buf, len);
7943   } else {
7944     size_t max_headers_len = 14 + 24 /* max IP */ + 60 /* max TCP */;
7945     if (len + max_headers_len > ifp->tx.len) len = ifp->tx.len - max_headers_len;
7946     if (tx_tcp(ifp, s->mac, c->rem.ip, TH_PUSH | TH_ACK, c->loc.port, c->rem.port,
7947                mg_htonl(s->seq), mg_htonl(s->ack), buf, len) > 0) {
7948       s->seq += (uint32_t) len;
7949       if (s->ttype == MIP_TTYPE_ACK) settmout(c, MIP_TTYPE_KEEPALIVE);
7950     } else {
7951       return MG_IO_ERR;
7952     }
7953   }
7954   return (long) len;
7955 }
7956
7957 long mg_io_recv(struct mg_connection *c, void *buf, size_t len) {
7958   struct connstate *s = (struct connstate *) (c + 1);
7959   if (s->raw.len == 0) return MG_IO_WAIT;
7960   if (len > s->raw.len) len = s->raw.len;
7961   memcpy(buf, s->raw.buf, len);
7962   mg_iobuf_del(&s->raw, 0, len);
7963   MG_DEBUG(("%lu", len));
7964   return (long) len;
7965 }
7966
7967 static void read_conn(struct mg_connection *c, struct pkt *pkt) {
7968   struct connstate *s = (struct connstate *) (c + 1);
7969   struct mg_iobuf *io = c->is_tls ? &s->raw : &c->recv;
7970   uint32_t seq = mg_ntohl(pkt->tcp->seq);
7971   s->raw.align = c->recv.align;
7972   if (pkt->tcp->flags & TH_FIN) {
7973     s->ack = mg_htonl(pkt->tcp->seq) + 1, s->seq = mg_htonl(pkt->tcp->ack);
7974     c->is_closing = 1;
7975   } else if (pkt->pay.len == 0) {
7976     // TODO(cpq): handle this peer's ACK
7977   } else if (seq != s->ack) {
7978     uint32_t ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
7979     if (s->ack == ack) {
7980       MG_VERBOSE(("ignoring duplicate pkt"));
7981     } else {
7982       // TODO(cpq): peer sent us SEQ which we don't expect. Retransmit rather
7983       // than close this connection
7984       mg_error(c, "SEQ != ACK: %x %x %x", seq, s->ack, ack);
7985     }
7986   } else if (io->size - io->len < pkt->pay.len &&
7987              !mg_iobuf_resize(io, io->len + pkt->pay.len)) {
7988     mg_error(c, "oom");
7989   } else {
7990     // Copy TCP payload into the IO buffer. If the connection is plain text, we
7991     // copy to c->recv. If the connection is TLS, this data is encrypted,
7992     // therefore we copy that encrypted data to the s->raw iobuffer instead,
7993     // and then call mg_tls_recv() to decrypt it. NOTE: mg_tls_recv() will
7994     // call back mg_io_recv() which grabs raw data from s->raw
7995     memcpy(&io->buf[io->len], pkt->pay.ptr, pkt->pay.len);
7996     io->len += pkt->pay.len;
7997
7998     MG_DEBUG(("%lu SEQ %x -> %x", c->id, mg_htonl(pkt->tcp->seq), s->ack));
7999     // Advance ACK counter
8000     s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
8001 #if 0
8002     // Send ACK immediately
8003     MG_DEBUG(("  imm ACK", c->id, mg_htonl(pkt->tcp->seq), s->ack));
8004     tx_tcp((struct mg_tcpip_if *) c->mgr->priv, c->rem.ip, TH_ACK, c->loc.port,
8005            c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
8006 #else
8007     // if not already running, setup a timer to send an ACK later
8008     if (s->ttype != MIP_TTYPE_ACK) settmout(c, MIP_TTYPE_ACK);
8009 #endif
8010
8011     if (c->is_tls) {
8012       // TLS connection. Make room for decrypted data in c->recv
8013       io = &c->recv;
8014       if (io->size - io->len < pkt->pay.len &&
8015           !mg_iobuf_resize(io, io->len + pkt->pay.len)) {
8016         mg_error(c, "oom");
8017       } else {
8018         // Decrypt data directly into c->recv
8019         long n = mg_tls_recv(c, &io->buf[io->len], io->size - io->len);
8020         if (n == MG_IO_ERR) {
8021           mg_error(c, "TLS recv error");
8022         } else if (n > 0) {
8023           // Decrypted successfully - trigger MG_EV_READ
8024           io->len += (size_t) n;
8025           mg_call(c, MG_EV_READ, &n);
8026         }
8027       }
8028     } else {
8029       // Plain text connection, data is already in c->recv, trigger MG_EV_READ
8030       mg_call(c, MG_EV_READ, &pkt->pay.len);
8031     }
8032   }
8033 }
8034
8035 static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
8036   struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
8037   struct connstate *s = c == NULL ? NULL : (struct connstate *) (c + 1);
8038 #if 0
8039   MG_INFO(("%lu %hhu %d", c ? c->id : 0, pkt->tcp->flags, (int) pkt->pay.len));
8040 #endif
8041   if (c != NULL && c->is_connecting && pkt->tcp->flags & (TH_SYN | TH_ACK)) {
8042     s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq) + 1;
8043     tx_tcp_pkt(ifp, pkt, TH_ACK, pkt->tcp->ack, NULL, 0);
8044     c->is_connecting = 0;  // Client connected
8045     settmout(c, MIP_TTYPE_KEEPALIVE);
8046     mg_call(c, MG_EV_CONNECT, NULL);  // Let user know
8047   } else if (c != NULL && c->is_connecting) {
8048     tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0);
8049   } else if (c != NULL && pkt->tcp->flags & TH_RST) {
8050     mg_error(c, "peer RST");  // RFC-1122 4.2.2.13
8051   } else if (c != NULL) {
8052 #if 0
8053     MG_DEBUG(("%lu %d %M:%hu -> %M:%hu", c->id, (int) pkt->raw.len,
8054               mg_print_ip4, &pkt->ip->src, mg_ntohs(pkt->tcp->sport),
8055               mg_print_ip4, &pkt->ip->dst, mg_ntohs(pkt->tcp->dport)));
8056     mg_hexdump(pkt->pay.buf, pkt->pay.len);
8057 #endif
8058     s->tmiss = 0;                         // Reset missed keep-alive counter
8059     if (s->ttype == MIP_TTYPE_KEEPALIVE)  // Advance keep-alive timer
8060       settmout(c,
8061                MIP_TTYPE_KEEPALIVE);  // unless a former ACK timeout is pending
8062     read_conn(c, pkt);  // Override timer with ACK timeout if needed
8063   } else if ((c = getpeer(ifp->mgr, pkt, true)) == NULL) {
8064     tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0);
8065   } else if (pkt->tcp->flags & TH_RST) {
8066     if (c->is_accepted) mg_error(c, "peer RST");  // RFC-1122 4.2.2.13
8067     // ignore RST if not connected
8068   } else if (pkt->tcp->flags & TH_SYN) {
8069     // Use peer's source port as ISN, in order to recognise the handshake
8070     uint32_t isn = mg_htonl((uint32_t) mg_ntohs(pkt->tcp->sport));
8071     tx_tcp_pkt(ifp, pkt, TH_SYN | TH_ACK, isn, NULL, 0);
8072   } else if (pkt->tcp->flags & TH_FIN) {
8073     tx_tcp_pkt(ifp, pkt, TH_FIN | TH_ACK, pkt->tcp->ack, NULL, 0);
8074   } else if (mg_htonl(pkt->tcp->ack) == mg_htons(pkt->tcp->sport) + 1U) {
8075     accept_conn(c, pkt);
8076   } else if (!c->is_accepted) {  // no peer
8077     tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0);
8078   } else {
8079     // MG_DEBUG(("dropped silently.."));
8080   }
8081 }
8082
8083 static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) {
8084   if (pkt->ip->proto == 1) {
8085     pkt->icmp = (struct icmp *) (pkt->ip + 1);
8086     if (pkt->pay.len < sizeof(*pkt->icmp)) return;
8087     mkpay(pkt, pkt->icmp + 1);
8088     rx_icmp(ifp, pkt);
8089   } else if (pkt->ip->proto == 17) {
8090     pkt->udp = (struct udp *) (pkt->ip + 1);
8091     if (pkt->pay.len < sizeof(*pkt->udp)) return;
8092     mkpay(pkt, pkt->udp + 1);
8093     MG_DEBUG(("UDP %M:%hu -> %M:%hu len %u", mg_print_ip4, &pkt->ip->src,
8094               mg_ntohs(pkt->udp->sport), mg_print_ip4, &pkt->ip->dst,
8095               mg_ntohs(pkt->udp->dport), (int) pkt->pay.len));
8096     if (pkt->udp->dport == mg_htons(68)) {
8097       pkt->dhcp = (struct dhcp *) (pkt->udp + 1);
8098       mkpay(pkt, pkt->dhcp + 1);
8099       rx_dhcp_client(ifp, pkt);
8100     } else if (ifp->enable_dhcp_server && pkt->udp->dport == mg_htons(67)) {
8101       pkt->dhcp = (struct dhcp *) (pkt->udp + 1);
8102       mkpay(pkt, pkt->dhcp + 1);
8103       rx_dhcp_server(ifp, pkt);
8104     } else {
8105       rx_udp(ifp, pkt);
8106     }
8107   } else if (pkt->ip->proto == 6) {
8108     pkt->tcp = (struct tcp *) (pkt->ip + 1);
8109     if (pkt->pay.len < sizeof(*pkt->tcp)) return;
8110     mkpay(pkt, pkt->tcp + 1);
8111     uint16_t iplen = mg_ntohs(pkt->ip->len);
8112     uint16_t off = (uint16_t) (sizeof(*pkt->ip) + ((pkt->tcp->off >> 4) * 4U));
8113     if (iplen >= off) pkt->pay.len = (size_t) (iplen - off);
8114     MG_DEBUG(("TCP %M:%hu -> %M:%hu len %u", mg_print_ip4, &pkt->ip->src,
8115               mg_ntohs(pkt->tcp->sport), mg_print_ip4, &pkt->ip->dst,
8116               mg_ntohs(pkt->tcp->dport), (int) pkt->pay.len));
8117     rx_tcp(ifp, pkt);
8118   }
8119 }
8120
8121 static void rx_ip6(struct mg_tcpip_if *ifp, struct pkt *pkt) {
8122   // MG_DEBUG(("IP %d", (int) len));
8123   if (pkt->ip6->proto == 1 || pkt->ip6->proto == 58) {
8124     pkt->icmp = (struct icmp *) (pkt->ip6 + 1);
8125     if (pkt->pay.len < sizeof(*pkt->icmp)) return;
8126     mkpay(pkt, pkt->icmp + 1);
8127     rx_icmp(ifp, pkt);
8128   } else if (pkt->ip6->proto == 17) {
8129     pkt->udp = (struct udp *) (pkt->ip6 + 1);
8130     if (pkt->pay.len < sizeof(*pkt->udp)) return;
8131     // MG_DEBUG(("  UDP %u %u -> %u", len, mg_htons(udp->sport),
8132     // mg_htons(udp->dport)));
8133     mkpay(pkt, pkt->udp + 1);
8134   }
8135 }
8136
8137 static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) {
8138   const uint8_t broadcast[] = {255, 255, 255, 255, 255, 255};
8139   struct pkt pkt;
8140   memset(&pkt, 0, sizeof(pkt));
8141   pkt.raw.ptr = (char *) buf;
8142   pkt.raw.len = len;
8143   pkt.eth = (struct eth *) buf;
8144   if (pkt.raw.len < sizeof(*pkt.eth)) return;  // Truncated - runt?
8145   if (ifp->enable_mac_check &&
8146       memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 &&
8147       memcmp(pkt.eth->dst, broadcast, sizeof(pkt.eth->dst)) != 0)
8148     return;
8149   if (ifp->enable_crc32_check && len > 4) {
8150     len -= 4;  // TODO(scaprile): check on bigendian
8151     uint32_t crc = mg_crc32(0, (const char *) buf, len);
8152     if (memcmp((void *) ((size_t) buf + len), &crc, sizeof(crc))) return;
8153   }
8154   if (pkt.eth->type == mg_htons(0x806)) {
8155     pkt.arp = (struct arp *) (pkt.eth + 1);
8156     if (sizeof(*pkt.eth) + sizeof(*pkt.arp) > pkt.raw.len) return;  // Truncated
8157     rx_arp(ifp, &pkt);
8158   } else if (pkt.eth->type == mg_htons(0x86dd)) {
8159     pkt.ip6 = (struct ip6 *) (pkt.eth + 1);
8160     if (pkt.raw.len < sizeof(*pkt.eth) + sizeof(*pkt.ip6)) return;  // Truncated
8161     if ((pkt.ip6->ver >> 4) != 0x6) return;                         // Not IP
8162     mkpay(&pkt, pkt.ip6 + 1);
8163     rx_ip6(ifp, &pkt);
8164   } else if (pkt.eth->type == mg_htons(0x800)) {
8165     pkt.ip = (struct ip *) (pkt.eth + 1);
8166     if (pkt.raw.len < sizeof(*pkt.eth) + sizeof(*pkt.ip)) return;  // Truncated
8167     // Truncate frame to what IP header tells us
8168     if ((size_t) mg_ntohs(pkt.ip->len) + sizeof(struct eth) < pkt.raw.len) {
8169       pkt.raw.len = (size_t) mg_ntohs(pkt.ip->len) + sizeof(struct eth);
8170     }
8171     if (pkt.raw.len < sizeof(*pkt.eth) + sizeof(*pkt.ip)) return;  // Truncated
8172     if ((pkt.ip->ver >> 4) != 4) return;                           // Not IP
8173     mkpay(&pkt, pkt.ip + 1);
8174     rx_ip(ifp, &pkt);
8175   } else {
8176     MG_DEBUG(("  Unknown eth type %x", mg_htons(pkt.eth->type)));
8177     mg_hexdump(buf, len >= 16 ? 16 : len);
8178   }
8179 }
8180
8181 static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t uptime_ms) {
8182   if (ifp == NULL || ifp->driver == NULL) return;
8183   bool expired_1000ms = mg_timer_expired(&ifp->timer_1000ms, 1000, uptime_ms);
8184   ifp->now = uptime_ms;
8185
8186   // Handle physical interface up/down status
8187   if (expired_1000ms && ifp->driver->up) {
8188     bool up = ifp->driver->up(ifp);
8189     bool current = ifp->state != MG_TCPIP_STATE_DOWN;
8190     if (up != current) {
8191       ifp->state = up == false               ? MG_TCPIP_STATE_DOWN
8192                    : ifp->enable_dhcp_client ? MG_TCPIP_STATE_UP
8193                                              : MG_TCPIP_STATE_READY;
8194       if (!up && ifp->enable_dhcp_client) ifp->ip = 0;
8195       onstatechange(ifp);
8196     }
8197   }
8198   if (ifp->state == MG_TCPIP_STATE_DOWN) return;
8199
8200   // If IP not configured, send DHCP
8201   if (ifp->ip == 0 && expired_1000ms) tx_dhcp_discover(ifp);
8202
8203   // Read data from the network
8204   if (ifp->driver->rx != NULL) {  // Polling driver. We must call it
8205     size_t len =
8206         ifp->driver->rx(ifp->recv_queue.buf, ifp->recv_queue.size, ifp);
8207     if (len > 0) mg_tcpip_rx(ifp, ifp->recv_queue.buf, len);
8208   } else {  // Interrupt-based driver. Fills recv queue itself
8209     char *buf;
8210     size_t len = mg_queue_next(&ifp->recv_queue, &buf);
8211     if (len > 0) {
8212       mg_tcpip_rx(ifp, buf, len);
8213       mg_queue_del(&ifp->recv_queue, len);
8214     }
8215   }
8216
8217   // Process timeouts
8218   for (struct mg_connection *c = ifp->mgr->conns; c != NULL; c = c->next) {
8219     if (c->is_udp || c->is_listening) continue;
8220     if (c->is_connecting || c->is_resolving) continue;
8221     struct connstate *s = (struct connstate *) (c + 1);
8222     if (uptime_ms > s->timer) {
8223       if (s->ttype == MIP_TTYPE_ACK) {
8224         MG_DEBUG(("%lu ack %x %x", c->id, s->seq, s->ack));
8225         tx_tcp(ifp, s->mac, c->rem.ip, TH_ACK, c->loc.port, c->rem.port,
8226                mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
8227       } else {
8228         if (s->tmiss++ > 2) {
8229           mg_error(c, "keepalive");
8230         } else {
8231           MG_DEBUG(("%lu keepalive", c->id));
8232           tx_tcp(ifp, s->mac, c->rem.ip, TH_ACK, c->loc.port, c->rem.port,
8233                  mg_htonl(s->seq - 1), mg_htonl(s->ack), "", 0);
8234         }
8235       }
8236       settmout(c, MIP_TTYPE_KEEPALIVE);
8237     }
8238   }
8239 }
8240
8241 // This function executes in interrupt context, thus it should copy data
8242 // somewhere fast. Note that newlib's malloc is not thread safe, thus use
8243 // our lock-free queue with preallocated buffer to copy data and return asap
8244 void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp) {
8245   char *p;
8246   if (mg_queue_book(&ifp->recv_queue, &p, len) >= len) {
8247     memcpy(p, buf, len);
8248     mg_queue_add(&ifp->recv_queue, len);
8249     ifp->nrecv++;
8250   } else {
8251     ifp->ndrop++;
8252   }
8253 }
8254
8255 void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
8256   // If MAC address is not set, make a random one
8257   if (ifp->mac[0] == 0 && ifp->mac[1] == 0 && ifp->mac[2] == 0 &&
8258       ifp->mac[3] == 0 && ifp->mac[4] == 0 && ifp->mac[5] == 0) {
8259     ifp->mac[0] = 0x02;  // Locally administered, unicast
8260     mg_random(&ifp->mac[1], sizeof(ifp->mac) - 1);
8261     MG_INFO(("MAC not set. Generated random: %M", mg_print_mac, ifp->mac));
8262   }
8263
8264   if (ifp->driver->init && !ifp->driver->init(ifp)) {
8265     MG_ERROR(("driver init failed"));
8266   } else {
8267     size_t framesize = 1540;
8268     ifp->tx.ptr = (char *) calloc(1, framesize), ifp->tx.len = framesize;
8269     if (ifp->recv_queue.size == 0)
8270       ifp->recv_queue.size = ifp->driver->rx ? framesize : 8192;
8271     ifp->recv_queue.buf = (char *) calloc(1, ifp->recv_queue.size);
8272     ifp->timer_1000ms = mg_millis();
8273     mgr->priv = ifp;
8274     ifp->mgr = mgr;
8275     mgr->extraconnsize = sizeof(struct connstate);
8276     if (ifp->ip == 0) ifp->enable_dhcp_client = true;
8277     memset(ifp->gwmac, 255, sizeof(ifp->gwmac));  // Set to broadcast
8278     mg_random(&ifp->eport, sizeof(ifp->eport));   // Random from 0 to 65535
8279     ifp->eport |=
8280         MG_EPHEMERAL_PORT_BASE;  // Random from MG_EPHEMERAL_PORT_BASE to 65535
8281     if (ifp->tx.ptr == NULL || ifp->recv_queue.buf == NULL) MG_ERROR(("OOM"));
8282   }
8283 }
8284
8285 void mg_tcpip_free(struct mg_tcpip_if *ifp) {
8286   free(ifp->recv_queue.buf);
8287   free((char *) ifp->tx.ptr);
8288 }
8289
8290 int mg_mkpipe(struct mg_mgr *m, mg_event_handler_t fn, void *d, bool udp) {
8291   (void) m, (void) fn, (void) d, (void) udp;
8292   MG_ERROR(("Not implemented"));
8293   return -1;
8294 }
8295
8296 static void send_syn(struct mg_connection *c) {
8297   struct connstate *s = (struct connstate *) (c + 1);
8298   uint32_t isn = mg_htonl((uint32_t) mg_ntohs(c->loc.port));
8299   struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
8300   tx_tcp(ifp, s->mac, c->rem.ip, TH_SYN, c->loc.port, c->rem.port, isn, 0, NULL,
8301          0);
8302 }
8303
8304 void mg_connect_resolved(struct mg_connection *c) {
8305   struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
8306   c->is_resolving = 0;
8307   if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE;
8308   c->loc.ip = ifp->ip;
8309   c->loc.port = mg_htons(ifp->eport++);
8310   MG_DEBUG(("%lu %M -> %M", c->id, mg_print_ip_port, &c->loc, mg_print_ip_port,
8311             &c->rem));
8312   mg_call(c, MG_EV_RESOLVE, NULL);
8313   if (((c->rem.ip & ifp->mask) == (ifp->ip & ifp->mask))) {
8314     // If we're in the same LAN, fire an ARP lookup. TODO(cpq): handle this!
8315     MG_DEBUG(("%lu ARP lookup...", c->id));
8316     arp_ask(ifp, c->rem.ip);
8317     c->is_arplooking = 1;
8318   } else if (c->rem.ip == (ifp->ip | ~ifp->mask)) {
8319     struct connstate *s = (struct connstate *) (c + 1);
8320     memset(s->mac, 0xFF, sizeof(s->mac));  // local broadcast
8321   } else if ((*((uint8_t *) &c->rem.ip) & 0xE0) == 0xE0) {
8322     struct connstate *s = (struct connstate *) (c + 1);  // 224 to 239, E0 to EF
8323     uint8_t mcastp[3] = {0x01, 0x00, 0x5E};              // multicast group
8324     memcpy(s->mac, mcastp, 3);
8325     memcpy(s->mac + 3, ((uint8_t *) &c->rem.ip) + 1, 3);  // 23 LSb
8326     s->mac[3] &= 0x7F;
8327   } else {
8328     struct connstate *s = (struct connstate *) (c + 1);
8329     memcpy(s->mac, ifp->gwmac, sizeof(ifp->gwmac));
8330     if (c->is_udp) {
8331       mg_call(c, MG_EV_CONNECT, NULL);
8332     } else {
8333       send_syn(c);
8334       c->is_connecting = 1;
8335     }
8336   }
8337 }
8338
8339 bool mg_open_listener(struct mg_connection *c, const char *url) {
8340   c->loc.port = mg_htons(mg_url_port(url));
8341   return true;
8342 }
8343
8344 static void write_conn(struct mg_connection *c) {
8345   long len = c->is_tls ? mg_tls_send(c, c->send.buf, c->send.len)
8346                        : mg_io_send(c, c->send.buf, c->send.len);
8347   if (len > 0) {
8348     mg_iobuf_del(&c->send, 0, (size_t) len);
8349     mg_call(c, MG_EV_WRITE, &len);
8350   }
8351 }
8352
8353 static void close_conn(struct mg_connection *c) {
8354   struct connstate *s = (struct connstate *) (c + 1);
8355   mg_iobuf_free(&s->raw);  // For TLS connections, release raw data
8356   if (c->is_udp == false && c->is_listening == false) {  // For TCP conns,
8357     struct mg_tcpip_if *ifp =
8358         (struct mg_tcpip_if *) c->mgr->priv;  // send TCP FIN
8359     tx_tcp(ifp, s->mac, c->rem.ip, TH_FIN | TH_ACK, c->loc.port, c->rem.port,
8360            mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
8361   }
8362   mg_close_conn(c);
8363 }
8364
8365 static bool can_write(struct mg_connection *c) {
8366   return c->is_connecting == 0 && c->is_resolving == 0 && c->send.len > 0 &&
8367          c->is_tls_hs == 0 && c->is_arplooking == 0;
8368 }
8369
8370 void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
8371   struct mg_connection *c, *tmp;
8372   uint64_t now = mg_millis();
8373   mg_tcpip_poll((struct mg_tcpip_if *) mgr->priv, now);
8374   mg_timer_poll(&mgr->timers, now);
8375   for (c = mgr->conns; c != NULL; c = tmp) {
8376     tmp = c->next;
8377     mg_call(c, MG_EV_POLL, &now);
8378     MG_VERBOSE(("%lu .. %c%c%c%c%c", c->id, c->is_tls ? 'T' : 't',
8379                 c->is_connecting ? 'C' : 'c', c->is_tls_hs ? 'H' : 'h',
8380                 c->is_resolving ? 'R' : 'r', c->is_closing ? 'C' : 'c'));
8381     if (c->is_tls_hs) mg_tls_handshake(c);
8382     if (can_write(c)) write_conn(c);
8383     if (c->is_draining && c->send.len == 0) c->is_closing = 1;
8384     if (c->is_closing) close_conn(c);
8385   }
8386   (void) ms;
8387 }
8388
8389 bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
8390   struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv;
8391   bool res = false;
8392   if (ifp->ip == 0 || ifp->state != MG_TCPIP_STATE_READY) {
8393     mg_error(c, "net down");
8394   } else if (c->is_udp) {
8395     struct connstate *s = (struct connstate *) (c + 1);
8396     tx_udp(ifp, s->mac, ifp->ip, c->loc.port, c->rem.ip, c->rem.port, buf, len);
8397     res = true;
8398   } else {
8399     res = mg_iobuf_add(&c->send, c->send.len, buf, len);
8400   }
8401   return res;
8402 }
8403 #endif  // MG_ENABLE_TCPIP