fuzz.c:_ZL9mock_initP11mg_tcpip_if:
    1|  5.44k|static bool mock_init(struct mg_tcpip_if *ifp) {
    2|  5.44k|  (void) ifp;
    3|  5.44k|  return true;
    4|  5.44k|}
fuzz.c:_ZL7mock_txPKvmP11mg_tcpip_if:
    6|  10.9k|static size_t mock_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
    7|  10.9k|  (void) buf, (void) len, (void) ifp;
    8|  10.9k|  return len;
    9|  10.9k|}
fuzz.c:_ZL7mock_rxPvmP11mg_tcpip_if:
   11|  5.44k|static size_t mock_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
   12|  5.44k|  (void) buf, (void) len, (void) ifp;
   13|  5.44k|  return 0;
   14|  5.44k|}
fuzz.c:_ZL7mock_upP11mg_tcpip_if:
   16|  5.44k|static bool mock_up(struct mg_tcpip_if *ifp) {
   17|  5.44k|  (void) ifp;
   18|  5.44k|  return true;
   19|  5.44k|}

LLVMFuzzerTestOneInput:
   24|  5.44k|int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   25|  5.44k|  mg_log_set(MG_LL_INFO);
  ------------------
  |  |  997|  5.44k|#define mg_log_set(level_) mg_log_level = (level_)
  ------------------
   26|       |
   27|  5.44k|  struct mg_dns_message dm;
   28|  5.44k|  mg_dns_parse(data, size, &dm);
   29|  5.44k|  mg_dns_parse(NULL, 0, &dm);
   30|       |
   31|  5.44k|  struct mg_http_message hm;
   32|  5.44k|  if (mg_http_parse((const char *) data, size, &hm) > 0) {
  ------------------
  |  Branch (32:7): [True: 2.29k, False: 3.15k]
  ------------------
   33|  2.29k|    mg_crc32(0, hm.method.buf, hm.method.len);
   34|  2.29k|    mg_crc32(0, hm.uri.buf, hm.uri.len);
   35|  2.29k|    mg_crc32(0, hm.uri.buf, hm.uri.len);
   36|  70.9k|    for (size_t i = 0; i < sizeof(hm.headers) / sizeof(hm.headers[0]); i++) {
  ------------------
  |  Branch (36:24): [True: 68.7k, False: 2.29k]
  ------------------
   37|  68.7k|      struct mg_str *k = &hm.headers[i].name, *v = &hm.headers[i].value;
   38|  68.7k|      mg_crc32(0, k->buf, k->len);
   39|  68.7k|      mg_crc32(0, v->buf, v->len);
   40|  68.7k|    }
   41|  2.29k|  }
   42|  5.44k|  mg_http_parse(NULL, 0, &hm);
   43|       |
   44|  5.44k|  struct mg_str body = mg_str_n((const char *) data, size);
   45|  5.44k|  char tmp[256];
   46|  5.44k|  mg_http_get_var(&body, "key", tmp, sizeof(tmp));
   47|  5.44k|  mg_http_get_var(&body, "key", NULL, 0);
   48|  5.44k|  mg_url_decode((char *) data, size, tmp, sizeof(tmp), 1);
   49|  5.44k|  mg_url_decode((char *) data, size, tmp, 1, 1);
   50|  5.44k|  mg_url_decode(NULL, 0, tmp, 1, 1);
   51|       |
   52|  5.44k|  struct mg_mqtt_message mm;
   53|  5.44k|  if (mg_mqtt_parse(data, size, 0, &mm) == MQTT_OK) {
  ------------------
  |  Branch (53:7): [True: 2.05k, False: 3.38k]
  ------------------
   54|  2.05k|    mg_crc32(0, mm.topic.buf, mm.topic.len);
   55|  2.05k|    mg_crc32(0, mm.data.buf, mm.data.len);
   56|  2.05k|    mg_crc32(0, mm.dgram.buf, mm.dgram.len);
   57|  2.05k|  }
   58|  5.44k|  mg_mqtt_parse(NULL, 0, 0, &mm);
   59|  5.44k|  if (mg_mqtt_parse(data, size, 5, &mm) == MQTT_OK) {
  ------------------
  |  Branch (59:7): [True: 2.04k, False: 3.39k]
  ------------------
   60|  2.04k|    mg_crc32(0, mm.topic.buf, mm.topic.len);
   61|  2.04k|    mg_crc32(0, mm.data.buf, mm.data.len);
   62|  2.04k|    mg_crc32(0, mm.dgram.buf, mm.dgram.len);
   63|  2.04k|  }
   64|  5.44k|  mg_mqtt_parse(NULL, 0, 5, &mm);
   65|       |
   66|  5.44k|  mg_sntp_parse(data, size);
   67|  5.44k|  mg_sntp_parse(NULL, 0);
   68|       |
   69|  5.44k|  char buf[size * 4 / 3 + 5];  // At least 4 chars and nul termination
   70|  5.44k|  mg_base64_decode((char *) data, size, buf, sizeof(buf));
   71|  5.44k|  mg_base64_decode(NULL, 0, buf, sizeof(buf));
   72|  5.44k|  mg_base64_encode(data, size, buf, sizeof(buf));
   73|  5.44k|  mg_base64_encode(NULL, 0, buf, sizeof(buf));
   74|       |
   75|  5.44k|  mg_match(mg_str_n((char *) data, size), mg_str_n((char *) data, size), NULL);
   76|       |
   77|  5.44k|  struct mg_str entry, s = mg_str_n((char *) data, size);
   78|   911k|  while (mg_span(s, &entry, &s, ',')) entry.len = 0;
  ------------------
  |  Branch (78:10): [True: 906k, False: 5.44k]
  ------------------
   79|       |
   80|  5.44k|  int n;
   81|  5.44k|  mg_json_get(mg_str_n((char *) data, size), "$", &n);
   82|  5.44k|  mg_json_get(mg_str_n((char *) data, size), "$.a.b", &n);
   83|  5.44k|  mg_json_get(mg_str_n((char *) data, size), "$[0]", &n);
   84|       |
   85|  5.44k|  if (size > 0) {
  ------------------
  |  Branch (85:7): [True: 5.44k, False: 0]
  ------------------
   86|  5.44k|    struct mg_tcpip_if mif = {.ip = 0x01020304,
   87|  5.44k|                              .mask = 255,
   88|  5.44k|                              .gw = 0x01010101,
   89|  5.44k|                              .driver = &mg_tcpip_driver_mock};
   90|  5.44k|    struct mg_mgr mgr;
   91|  5.44k|    mg_mgr_init(&mgr);
   92|  5.44k|    mg_tcpip_init(&mgr, &mif);
   93|       |
   94|       |    // Make a copy of the random data, in order to modify it
   95|  5.44k|    void *pkt = malloc(size);
   96|  5.44k|    struct eth *eth = (struct eth *) pkt;
   97|  5.44k|    memcpy(pkt, data, size);
   98|  5.44k|    if (size > sizeof(*eth)) {
  ------------------
  |  Branch (98:9): [True: 3.61k, False: 1.82k]
  ------------------
   99|  3.61k|      static size_t i;
  100|  3.61k|      uint16_t eth_types[] = {0x800, 0x800, 0x806, 0x86dd};
  101|  3.61k|      memcpy(eth->dst, mif.mac, 6);  // Set valid destination MAC
  102|  3.61k|      eth->type = mg_htons(eth_types[i++]);
  ------------------
  |  | 1113|  3.61k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  103|  3.61k|      if (i >= sizeof(eth_types) / sizeof(eth_types[0])) i = 0;
  ------------------
  |  Branch (103:11): [True: 903, False: 2.71k]
  ------------------
  104|  3.61k|    }
  105|       |
  106|  5.44k|    mg_tcpip_rx(&mif, pkt, size);
  107|       |
  108|       |    // Test HTTP serving
  109|  5.44k|    const char *url = "http://localhost:12345";
  110|  5.44k|    struct mg_connection *c = mg_http_connect(&mgr, url, fn, NULL);
  111|  5.44k|    mg_iobuf_add(&c->recv, 0, data, size);
  112|  5.44k|    c->pfn(c, MG_EV_READ, NULL); // manually invoke protocol event handler
  113|       |
  114|  5.44k|    mg_mgr_free(&mgr);
  115|  5.44k|    free(pkt);
  116|  5.44k|    mg_tcpip_free(&mif);
  117|  5.44k|  }
  118|       |
  119|  5.44k|  return 0;
  120|  5.44k|}
fuzz.c:_ZL2fnP13mg_connectioniPv:
   17|   696k|static void fn(struct mg_connection *c, int ev, void *ev_data) {
   18|   696k|  struct mg_http_serve_opts opts = {.root_dir = "."};
   19|   696k|  if (ev == MG_EV_HTTP_MSG) {
  ------------------
  |  Branch (19:7): [True: 333k, False: 362k]
  ------------------
   20|   333k|    mg_http_serve_dir(c, (struct mg_http_message *) ev_data, &opts);
   21|   333k|  }
   22|   696k|}

mg_base64_update:
   57|   175M|size_t mg_base64_update(unsigned char ch, char *to, size_t n) {
   58|   175M|  unsigned long rem = (n & 3) % 3;
   59|   175M|  if (rem == 0) {
  ------------------
  |  Branch (59:7): [True: 58.4M, False: 116M]
  ------------------
   60|  58.4M|    to[n] = (char) mg_base64_encode_single(ch >> 2);
   61|  58.4M|    to[++n] = (char) ((ch & 3) << 4);
   62|   116M|  } else if (rem == 1) {
  ------------------
  |  Branch (62:14): [True: 58.4M, False: 58.4M]
  ------------------
   63|  58.4M|    to[n] = (char) mg_base64_encode_single(to[n] | (ch >> 4));
   64|  58.4M|    to[++n] = (char) ((ch & 15) << 2);
   65|  58.4M|  } else {
   66|  58.4M|    to[n] = (char) mg_base64_encode_single(to[n] | (ch >> 6));
   67|  58.4M|    to[++n] = (char) mg_base64_encode_single(ch & 63);
   68|  58.4M|    n++;
   69|  58.4M|  }
   70|   175M|  return n;
   71|   175M|}
mg_base64_final:
   73|  10.8k|size_t mg_base64_final(char *to, size_t n) {
   74|  10.8k|  size_t saved = n;
   75|       |  // printf("---[%.*s]\n", n, to);
   76|  10.8k|  if (n & 3) n = mg_base64_update(0, to, n);
  ------------------
  |  Branch (76:7): [True: 3.59k, False: 7.28k]
  ------------------
   77|  10.8k|  if ((saved & 3) == 2) n--;
  ------------------
  |  Branch (77:7): [True: 1.84k, False: 9.03k]
  ------------------
   78|       |  // printf("    %d[%.*s]\n", n, n, to);
   79|  16.2k|  while (n & 3) to[n++] = '=';
  ------------------
  |  Branch (79:10): [True: 5.33k, False: 10.8k]
  ------------------
   80|  10.8k|  to[n] = '\0';
   81|  10.8k|  return n;
   82|  10.8k|}
mg_base64_encode:
   84|  10.8k|size_t mg_base64_encode(const unsigned char *p, size_t n, char *to, size_t dl) {
   85|  10.8k|  size_t i, len = 0;
   86|  10.8k|  if (dl > 0) to[0] = '\0';
  ------------------
  |  Branch (86:7): [True: 10.8k, False: 0]
  ------------------
   87|  10.8k|  if (dl < ((n / 3) + (n % 3 ? 1 : 0)) * 4 + 1) return 0;
  ------------------
  |  Branch (87:7): [True: 0, False: 10.8k]
  |  Branch (87:24): [True: 3.59k, False: 7.28k]
  ------------------
   88|   175M|  for (i = 0; i < n; i++) len = mg_base64_update(p[i], to, len);
  ------------------
  |  Branch (88:15): [True: 175M, False: 10.8k]
  ------------------
   89|  10.8k|  len = mg_base64_final(to, len);
   90|  10.8k|  return len;
   91|  10.8k|}
mg_base64_decode:
   93|  10.8k|size_t mg_base64_decode(const char *src, size_t n, char *dst, size_t dl) {
   94|  10.8k|  const char *end = src == NULL ? NULL : src + n;  // Cannot add to NULL
  ------------------
  |  Branch (94:21): [True: 5.44k, False: 5.44k]
  ------------------
   95|  10.8k|  size_t len = 0;
   96|  10.8k|  if (dl < n / 4 * 3 + 1) goto fail;
  ------------------
  |  Branch (96:7): [True: 0, False: 10.8k]
  ------------------
   97|  1.92M|  while (src != NULL && src + 3 < end) {
  ------------------
  |  Branch (97:10): [True: 1.92M, False: 5.44k]
  |  Branch (97:25): [True: 1.91M, False: 647]
  ------------------
   98|  1.91M|    int a = mg_base64_decode_single(src[0]),
   99|  1.91M|        b = mg_base64_decode_single(src[1]),
  100|  1.91M|        c = mg_base64_decode_single(src[2]),
  101|  1.91M|        d = mg_base64_decode_single(src[3]);
  102|  1.91M|    if (a == 64 || a < 0 || b == 64 || b < 0 || c < 0 || d < 0) {
  ------------------
  |  Branch (102:9): [True: 32, False: 1.91M]
  |  Branch (102:20): [True: 2.72k, False: 1.91M]
  |  Branch (102:29): [True: 3, False: 1.91M]
  |  Branch (102:40): [True: 1.67k, False: 1.91M]
  |  Branch (102:49): [True: 185, False: 1.91M]
  |  Branch (102:58): [True: 178, False: 1.91M]
  ------------------
  103|  4.79k|      goto fail;
  104|  4.79k|    }
  105|  1.91M|    dst[len++] = (char) ((a << 2) | (b >> 4));
  106|  1.91M|    if (src[2] != '=') {
  ------------------
  |  Branch (106:9): [True: 1.91M, False: 623]
  ------------------
  107|  1.91M|      dst[len++] = (char) ((b << 4) | (c >> 2));
  108|  1.91M|      if (src[3] != '=') dst[len++] = (char) ((c << 6) | d);
  ------------------
  |  Branch (108:11): [True: 1.91M, False: 224]
  ------------------
  109|  1.91M|    }
  110|  1.91M|    src += 4;
  111|  1.91M|  }
  112|  6.08k|  dst[len] = '\0';
  113|  6.08k|  return len;
  114|  4.79k|fail:
  115|  4.79k|  if (dl > 0) dst[0] = '\0';
  ------------------
  |  Branch (115:7): [True: 4.79k, False: 0]
  ------------------
  116|  4.79k|  return 0;
  117|  10.8k|}
mg_resolve_cancel:
  145|  5.44k|void mg_resolve_cancel(struct mg_connection *c) {
  146|  5.44k|  struct dns_data *tmp, *d;
  147|  5.44k|  struct dns_data **head = (struct dns_data **) &c->mgr->active_dns_requests;
  148|  5.44k|  for (d = *head; d != NULL; d = tmp) {
  ------------------
  |  Branch (148:19): [True: 0, False: 5.44k]
  ------------------
  149|      0|    tmp = d->next;
  150|      0|    if (d->c == c) mg_dns_free(head, d);
  ------------------
  |  Branch (150:9): [True: 0, False: 0]
  ------------------
  151|      0|  }
  152|  5.44k|}
mg_dns_parse_rr:
  197|    893|                       bool is_question, struct mg_dns_rr *rr) {
  198|    893|  const uint8_t *s = buf + ofs, *e = &buf[len];
  199|       |
  200|    893|  memset(rr, 0, sizeof(*rr));
  201|    893|  if (len < sizeof(struct mg_dns_header)) return 0;  // Too small
  ------------------
  |  Branch (201:7): [True: 0, False: 893]
  ------------------
  202|    893|  if (len > 512) return 0;  //  Too large, we don't expect that
  ------------------
  |  Branch (202:7): [True: 93, False: 800]
  ------------------
  203|    800|  if (s >= e) return 0;     //  Overflow
  ------------------
  |  Branch (203:7): [True: 98, False: 702]
  ------------------
  204|       |
  205|    702|  if ((rr->nlen = (uint16_t) mg_dns_parse_name(buf, len, ofs, NULL, 0)) == 0)
  ------------------
  |  Branch (205:7): [True: 83, False: 619]
  ------------------
  206|     83|    return 0;
  207|    619|  s += rr->nlen + 4;
  208|    619|  if (s > e) return 0;
  ------------------
  |  Branch (208:7): [True: 68, False: 551]
  ------------------
  209|    551|  rr->atype = (uint16_t) (((uint16_t) s[-4] << 8) | s[-3]);
  210|    551|  rr->aclass = (uint16_t) (((uint16_t) s[-2] << 8) | s[-1]);
  211|    551|  if (is_question) return (size_t) (rr->nlen + 4);
  ------------------
  |  Branch (211:7): [True: 128, False: 423]
  ------------------
  212|       |
  213|    423|  s += 6;
  214|    423|  if (s > e) return 0;
  ------------------
  |  Branch (214:7): [True: 21, False: 402]
  ------------------
  215|    402|  rr->alen = (uint16_t) (((uint16_t) s[-2] << 8) | s[-1]);
  216|    402|  if (s + rr->alen > e) return 0;
  ------------------
  |  Branch (216:7): [True: 119, False: 283]
  ------------------
  217|    283|  return (size_t) (rr->nlen + rr->alen + 10);
  218|    402|}
mg_dns_parse:
  220|  10.8k|bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
  221|  10.8k|  const struct mg_dns_header *h = (struct mg_dns_header *) buf;
  222|  10.8k|  struct mg_dns_rr rr;
  223|  10.8k|  size_t i, n, num_answers, ofs = sizeof(*h);
  224|  10.8k|  memset(dm, 0, sizeof(*dm));
  225|       |
  226|  10.8k|  if (len < sizeof(*h)) return 0;                // Too small, headers dont fit
  ------------------
  |  Branch (226:7): [True: 6.95k, False: 3.92k]
  ------------------
  227|  3.92k|  if (mg_ntohs(h->num_questions) > 1) return 0;  // Sanity
  ------------------
  |  Branch (227:7): [True: 3.42k, False: 506]
  ------------------
  228|    506|  num_answers = mg_ntohs(h->num_answers);
  229|    506|  if (num_answers > 10) {
  ------------------
  |  Branch (229:7): [True: 450, False: 56]
  ------------------
  230|    450|    MG_DEBUG(("Got %u answers, ignoring beyond 10th one", num_answers));
  ------------------
  |  | 1016|    450|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1009|    450|  do {                      \
  |  |  |  | 1010|    450|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|    450|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  231|    450|    num_answers = 10;  // Sanity cap
  232|    450|  }
  233|    506|  dm->txnid = mg_ntohs(h->txnid);
  234|       |
  235|    634|  for (i = 0; i < mg_ntohs(h->num_questions); i++) {
  ------------------
  |  Branch (235:15): [True: 251, False: 383]
  ------------------
  236|    251|    if ((n = mg_dns_parse_rr(buf, len, ofs, true, &rr)) == 0) return false;
  ------------------
  |  Branch (236:9): [True: 123, False: 128]
  ------------------
  237|       |    // MG_INFO(("Q %lu %lu %hu/%hu", ofs, n, rr.atype, rr.aclass));
  238|    128|    ofs += n;
  239|    128|  }
  240|    664|  for (i = 0; i < num_answers; i++) {
  ------------------
  |  Branch (240:15): [True: 642, False: 22]
  ------------------
  241|    642|    if ((n = mg_dns_parse_rr(buf, len, ofs, false, &rr)) == 0) return false;
  ------------------
  |  Branch (241:9): [True: 359, False: 283]
  ------------------
  242|       |    // MG_INFO(("A -- %lu %lu %hu/%hu %s", ofs, n, rr.atype, rr.aclass,
  243|       |    // dm->name));
  244|    283|    mg_dns_parse_name(buf, len, ofs, dm->name, sizeof(dm->name));
  245|    283|    ofs += n;
  246|       |
  247|    283|    if (rr.alen == 4 && rr.atype == 1 && rr.aclass == 1) {
  ------------------
  |  Branch (247:9): [True: 63, False: 220]
  |  Branch (247:25): [True: 36, False: 27]
  |  Branch (247:42): [True: 1, False: 35]
  ------------------
  248|      1|      dm->addr.is_ip6 = false;
  249|      1|      memcpy(&dm->addr.ip, &buf[ofs - 4], 4);
  250|      1|      dm->resolved = true;
  251|      1|      break;  // Return success
  252|    282|    } else if (rr.alen == 16 && rr.atype == 28 && rr.aclass == 1) {
  ------------------
  |  Branch (252:16): [True: 57, False: 225]
  |  Branch (252:33): [True: 32, False: 25]
  |  Branch (252:51): [True: 1, False: 31]
  ------------------
  253|      1|      dm->addr.is_ip6 = true;
  254|      1|      memcpy(&dm->addr.ip, &buf[ofs - 16], 16);
  255|      1|      dm->resolved = true;
  256|      1|      break;  // Return success
  257|      1|    }
  258|    283|  }
  259|     24|  return true;
  260|    383|}
mg_resolve:
  377|  5.44k|void mg_resolve(struct mg_connection *c, const char *url) {
  378|  5.44k|  struct mg_str host = mg_url_host(url);
  379|  5.44k|  c->rem.port = mg_htons(mg_url_port(url));
  ------------------
  |  | 1113|  5.44k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  380|  5.44k|  if (mg_aton(host, &c->rem)) {
  ------------------
  |  Branch (380:7): [True: 5.44k, False: 0]
  ------------------
  381|       |    // host is an IP address, do not fire name resolution
  382|  5.44k|    mg_connect_resolved(c);
  383|  5.44k|  } else {
  384|       |    // host is not an IP, send DNS resolution request
  385|      0|    struct mg_dns *dns = c->mgr->use_dns6 ? &c->mgr->dns6 : &c->mgr->dns4;
  ------------------
  |  Branch (385:26): [True: 0, False: 0]
  ------------------
  386|      0|    mg_sendnsreq(c, &host, c->mgr->dnstimeout, dns, c->mgr->use_dns6);
  387|      0|  }
  388|  5.44k|}
mg_call:
  399|   696k|void mg_call(struct mg_connection *c, int ev, void *ev_data) {
  400|       |#if MG_ENABLE_PROFILE
  401|       |  const char *names[] = {
  402|       |      "EV_ERROR",    "EV_OPEN",      "EV_POLL",      "EV_RESOLVE",
  403|       |      "EV_CONNECT",  "EV_ACCEPT",    "EV_TLS_HS",    "EV_READ",
  404|       |      "EV_WRITE",    "EV_CLOSE",     "EV_HTTP_MSG",  "EV_HTTP_CHUNK",
  405|       |      "EV_WS_OPEN",  "EV_WS_MSG",    "EV_WS_CTL",    "EV_MQTT_CMD",
  406|       |      "EV_MQTT_MSG", "EV_MQTT_OPEN", "EV_SNTP_TIME", "EV_USER"};
  407|       |  if (ev != MG_EV_POLL && ev < (int) (sizeof(names) / sizeof(names[0]))) {
  408|       |    MG_PROF_ADD(c, names[ev]);
  409|       |  }
  410|       |#endif
  411|       |  // Fire protocol handler first, user handler second. See #2559
  412|   696k|  if (c->pfn != NULL) c->pfn(c, ev, ev_data);
  ------------------
  |  Branch (412:7): [True: 685k, False: 10.8k]
  ------------------
  413|   696k|  if (c->fn != NULL) c->fn(c, ev, ev_data);
  ------------------
  |  Branch (413:7): [True: 696k, False: 0]
  ------------------
  414|   696k|}
mg_error:
  416|  5.88k|void mg_error(struct mg_connection *c, const char *fmt, ...) {
  417|  5.88k|  char buf[64];
  418|  5.88k|  va_list ap;
  419|  5.88k|  va_start(ap, fmt);
  420|  5.88k|  mg_vsnprintf(buf, sizeof(buf), fmt, &ap);
  421|  5.88k|  va_end(ap);
  422|  5.88k|  MG_ERROR(("%lu %ld %s", c->id, c->fd, buf));
  ------------------
  |  | 1014|  5.88k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|  5.88k|  do {                      \
  |  |  |  | 1010|  5.88k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|  5.88k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  423|  5.88k|  c->is_closing = 1;             // Set is_closing before sending MG_EV_CALL
  424|  5.88k|  mg_call(c, MG_EV_ERROR, buf);  // Let user handler override it
  425|  5.88k|}
mg_vxprintf:
  650|  15.7M|                   va_list *ap) {
  651|  15.7M|  size_t i = 0, n = 0;
  652|   436M|  while (fmt[i] != '\0') {
  ------------------
  |  Branch (652:10): [True: 420M, False: 15.7M]
  ------------------
  653|   420M|    if (fmt[i] == '%') {
  ------------------
  |  Branch (653:9): [True: 45.2M, False: 375M]
  ------------------
  654|  45.2M|      size_t j, k, x = 0, is_long = 0, w = 0 /* width */, pr = ~0U /* prec */;
  655|  45.2M|      char pad = ' ', minus = 0, c = fmt[++i];
  656|  45.2M|      if (c == '#') x++, c = fmt[++i];
  ------------------
  |  Branch (656:11): [True: 0, False: 45.2M]
  ------------------
  657|  45.2M|      if (c == '-') minus++, c = fmt[++i];
  ------------------
  |  Branch (657:11): [True: 77.0k, False: 45.2M]
  ------------------
  658|  45.2M|      if (c == '0') pad = '0', c = fmt[++i];
  ------------------
  |  Branch (658:11): [True: 0, False: 45.2M]
  ------------------
  659|  45.4M|      while (is_digit(c)) w *= 10, w += (size_t) (c - '0'), c = fmt[++i];
  ------------------
  |  Branch (659:14): [True: 154k, False: 45.2M]
  ------------------
  660|  45.2M|      if (c == '.') {
  ------------------
  |  Branch (660:11): [True: 4.12M, False: 41.1M]
  ------------------
  661|  4.12M|        c = fmt[++i];
  662|  4.12M|        if (c == '*') {
  ------------------
  |  Branch (662:13): [True: 4.12M, False: 0]
  ------------------
  663|  4.12M|          pr = (size_t) va_arg(*ap, int);
  664|  4.12M|          c = fmt[++i];
  665|  4.12M|        } else {
  666|      0|          pr = 0;
  667|      0|          while (is_digit(c)) pr *= 10, pr += (size_t) (c - '0'), c = fmt[++i];
  ------------------
  |  Branch (667:18): [True: 0, False: 0]
  ------------------
  668|      0|        }
  669|  4.12M|      }
  670|  45.2M|      while (c == 'h') c = fmt[++i];  // Treat h and hh as int
  ------------------
  |  Branch (670:14): [True: 0, False: 45.2M]
  ------------------
  671|  45.2M|      if (c == 'l') {
  ------------------
  |  Branch (671:11): [True: 10.6M, False: 34.6M]
  ------------------
  672|  10.6M|        is_long++, c = fmt[++i];
  673|  10.6M|        if (c == 'l') is_long++, c = fmt[++i];
  ------------------
  |  Branch (673:13): [True: 3.78M, False: 6.88M]
  ------------------
  674|  10.6M|      }
  675|  45.2M|      if (c == 'p') x = 1, is_long = 1;
  ------------------
  |  Branch (675:11): [True: 0, False: 45.2M]
  ------------------
  676|  45.2M|      if (c == 'd' || c == 'u' || c == 'x' || c == 'X' || c == 'p' ||
  ------------------
  |  Branch (676:11): [True: 3.85M, False: 41.4M]
  |  Branch (676:23): [True: 6.88M, False: 34.5M]
  |  Branch (676:35): [True: 0, False: 34.5M]
  |  Branch (676:47): [True: 0, False: 34.5M]
  |  Branch (676:59): [True: 0, False: 34.5M]
  ------------------
  677|  45.2M|          c == 'g' || c == 'f') {
  ------------------
  |  Branch (677:11): [True: 0, False: 34.5M]
  |  Branch (677:23): [True: 0, False: 34.5M]
  ------------------
  678|  10.7M|        bool s = (c == 'd'), h = (c == 'x' || c == 'X' || c == 'p');
  ------------------
  |  Branch (678:35): [True: 0, False: 10.7M]
  |  Branch (678:47): [True: 0, False: 10.7M]
  |  Branch (678:59): [True: 0, False: 10.7M]
  ------------------
  679|  10.7M|        char tmp[40];
  680|  10.7M|        size_t xl = x ? 2 : 0;
  ------------------
  |  Branch (680:21): [True: 0, False: 10.7M]
  ------------------
  681|  10.7M|        if (c == 'g' || c == 'f') {
  ------------------
  |  Branch (681:13): [True: 0, False: 10.7M]
  |  Branch (681:25): [True: 0, False: 10.7M]
  ------------------
  682|      0|          double v = va_arg(*ap, double);
  683|      0|          if (pr == ~0U) pr = 6;
  ------------------
  |  Branch (683:15): [True: 0, False: 0]
  ------------------
  684|      0|          k = mg_dtoa(tmp, sizeof(tmp), v, (int) pr, c == 'g');
  685|  10.7M|        } else if (is_long == 2) {
  ------------------
  |  Branch (685:20): [True: 3.78M, False: 6.96M]
  ------------------
  686|  3.78M|          int64_t v = va_arg(*ap, int64_t);
  687|  3.78M|          k = mg_lld(tmp, v, s, h);
  688|  6.96M|        } else if (is_long == 1) {
  ------------------
  |  Branch (688:20): [True: 6.88M, False: 77.0k]
  ------------------
  689|  6.88M|          long v = va_arg(*ap, long);
  690|  6.88M|          k = mg_lld(tmp, s ? (int64_t) v : (int64_t) (unsigned long) v, s, h);
  ------------------
  |  Branch (690:27): [True: 0, False: 6.88M]
  ------------------
  691|  6.88M|        } else {
  692|  77.0k|          int v = va_arg(*ap, int);
  693|  77.0k|          k = mg_lld(tmp, s ? (int64_t) v : (int64_t) (unsigned) v, s, h);
  ------------------
  |  Branch (693:27): [True: 77.0k, False: 0]
  ------------------
  694|  77.0k|        }
  695|  10.7M|        for (j = 0; j < xl && w > 0; j++) w--;
  ------------------
  |  Branch (695:21): [True: 0, False: 10.7M]
  |  Branch (695:31): [True: 0, False: 0]
  ------------------
  696|  10.7M|        for (j = 0; pad == ' ' && !minus && k < w && j + k < w; j++)
  ------------------
  |  Branch (696:21): [True: 10.7M, False: 0]
  |  Branch (696:35): [True: 10.6M, False: 77.0k]
  |  Branch (696:45): [True: 0, False: 10.6M]
  |  Branch (696:54): [True: 0, False: 0]
  ------------------
  697|      0|          n += scpy(out, param, &pad, 1);
  698|  10.7M|        n += scpy(out, param, (char *) "0x", xl);
  699|  10.7M|        for (j = 0; pad == '0' && k < w && j + k < w; j++)
  ------------------
  |  Branch (699:21): [True: 0, False: 10.7M]
  |  Branch (699:35): [True: 0, False: 0]
  |  Branch (699:44): [True: 0, False: 0]
  ------------------
  700|      0|          n += scpy(out, param, &pad, 1);
  701|  10.7M|        n += scpy(out, param, tmp, k);
  702|  11.3M|        for (j = 0; pad == ' ' && minus && k < w && j + k < w; j++)
  ------------------
  |  Branch (702:21): [True: 11.3M, False: 0]
  |  Branch (702:35): [True: 693k, False: 10.6M]
  |  Branch (702:44): [True: 693k, False: 0]
  |  Branch (702:53): [True: 616k, False: 77.0k]
  ------------------
  703|   616k|          n += scpy(out, param, &pad, 1);
  704|  34.5M|      } else if (c == 'm' || c == 'M') {
  ------------------
  |  Branch (704:18): [True: 0, False: 34.5M]
  |  Branch (704:30): [True: 0, False: 34.5M]
  ------------------
  705|      0|        mg_pm_t f = va_arg(*ap, mg_pm_t);
  706|      0|        if (c == 'm') out('"', param);
  ------------------
  |  Branch (706:13): [True: 0, False: 0]
  ------------------
  707|      0|        n += f(out, param, ap);
  708|      0|        if (c == 'm') n += 2, out('"', param);
  ------------------
  |  Branch (708:13): [True: 0, False: 0]
  ------------------
  709|  34.5M|      } else if (c == 'c') {
  ------------------
  |  Branch (709:18): [True: 3.28M, False: 31.2M]
  ------------------
  710|  3.28M|        int ch = va_arg(*ap, int);
  711|  3.28M|        out((char) ch, param);
  712|  3.28M|        n++;
  713|  31.2M|      } else if (c == 's') {
  ------------------
  |  Branch (713:18): [True: 31.2M, False: 0]
  ------------------
  714|  31.2M|        char *p = va_arg(*ap, char *);
  715|  31.2M|        if (pr == ~0U) pr = p == NULL ? 0 : strlen(p);
  ------------------
  |  Branch (715:13): [True: 27.1M, False: 4.12M]
  |  Branch (715:29): [True: 0, False: 27.1M]
  ------------------
  716|  31.2M|        for (j = 0; !minus && pr < w && j + pr < w; j++)
  ------------------
  |  Branch (716:21): [True: 31.2M, False: 0]
  |  Branch (716:31): [True: 0, False: 31.2M]
  |  Branch (716:41): [True: 0, False: 0]
  ------------------
  717|      0|          n += scpy(out, param, &pad, 1);
  718|  31.2M|        n += scpy(out, param, p, pr);
  719|  31.2M|        for (j = 0; minus && pr < w && j + pr < w; j++)
  ------------------
  |  Branch (719:21): [True: 0, False: 31.2M]
  |  Branch (719:30): [True: 0, False: 0]
  |  Branch (719:40): [True: 0, False: 0]
  ------------------
  720|      0|          n += scpy(out, param, &pad, 1);
  721|  31.2M|      } else if (c == '%') {
  ------------------
  |  Branch (721:18): [True: 0, False: 0]
  ------------------
  722|      0|        out('%', param);
  723|      0|        n++;
  724|      0|      } else {
  725|      0|        out('%', param);
  726|      0|        out(c, param);
  727|      0|        n += 2;
  728|      0|      }
  729|  45.2M|      i++;
  730|   375M|    } else {
  731|   375M|      out(fmt[i], param), n++, i++;
  732|   375M|    }
  733|   420M|  }
  734|  15.7M|  return n;
  735|  15.7M|}
mg_fs_open:
  744|  77.4k|struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags) {
  745|  77.4k|  struct mg_fd *fd = (struct mg_fd *) calloc(1, sizeof(*fd));
  746|  77.4k|  if (fd != NULL) {
  ------------------
  |  Branch (746:7): [True: 77.4k, False: 0]
  ------------------
  747|  77.4k|    fd->fd = fs->op(path, flags);
  748|  77.4k|    fd->fs = fs;
  749|  77.4k|    if (fd->fd == NULL) {
  ------------------
  |  Branch (749:9): [True: 77.4k, False: 0]
  ------------------
  750|  77.4k|      free(fd);
  751|  77.4k|      fd = NULL;
  752|  77.4k|    }
  753|  77.4k|  }
  754|  77.4k|  return fd;
  755|  77.4k|}
mg_fs_close:
  757|  77.0k|void mg_fs_close(struct mg_fd *fd) {
  758|  77.0k|  if (fd != NULL) {
  ------------------
  |  Branch (758:7): [True: 0, False: 77.0k]
  ------------------
  759|      0|    fd->fs->cl(fd->fd);
  760|      0|    free(fd);
  761|      0|  }
  762|  77.0k|}
_Z12mg_to_size_t6mg_strPm:
 1385|  1.51k|bool mg_to_size_t(struct mg_str str, size_t *val) {
 1386|  1.51k|  size_t i = 0, max = (size_t) -1, max2 = max / 10, result = 0, ndigits = 0;
 1387|  1.51k|  while (i < str.len && (str.buf[i] == ' ' || str.buf[i] == '\t')) i++;
  ------------------
  |  Branch (1387:10): [True: 1.51k, False: 3]
  |  Branch (1387:26): [True: 0, False: 1.51k]
  |  Branch (1387:47): [True: 0, False: 1.51k]
  ------------------
 1388|  1.51k|  if (i < str.len && str.buf[i] == '-') return false;
  ------------------
  |  Branch (1388:7): [True: 1.51k, False: 3]
  |  Branch (1388:22): [True: 3, False: 1.50k]
  ------------------
 1389|  6.47M|  while (i < str.len && str.buf[i] >= '0' && str.buf[i] <= '9') {
  ------------------
  |  Branch (1389:10): [True: 6.47M, False: 1.32k]
  |  Branch (1389:25): [True: 6.47M, False: 131]
  |  Branch (1389:46): [True: 6.47M, False: 37]
  ------------------
 1390|  6.47M|    size_t digit = (size_t) (str.buf[i] - '0');
 1391|  6.47M|    if (result > max2) return false;  // Overflow
  ------------------
  |  Branch (1391:9): [True: 13, False: 6.47M]
  ------------------
 1392|  6.47M|    result *= 10;
 1393|  6.47M|    if (result > max - digit) return false;  // Overflow
  ------------------
  |  Branch (1393:9): [True: 3, False: 6.47M]
  ------------------
 1394|  6.47M|    result += digit;
 1395|  6.47M|    i++, ndigits++;
 1396|  6.47M|  }
 1397|  11.0k|  while (i < str.len && (str.buf[i] == ' ' || str.buf[i] == '\t')) i++;
  ------------------
  |  Branch (1397:10): [True: 9.74k, False: 1.32k]
  |  Branch (1397:26): [True: 9.24k, False: 508]
  |  Branch (1397:47): [True: 340, False: 168]
  ------------------
 1398|  1.49k|  if (ndigits == 0) return false;  // #2322: Content-Length = 1 * DIGIT
  ------------------
  |  Branch (1398:7): [True: 29, False: 1.46k]
  ------------------
 1399|  1.46k|  if (i != str.len) return false;  // Ditto
  ------------------
  |  Branch (1399:7): [True: 142, False: 1.32k]
  ------------------
 1400|  1.32k|  *val = (size_t) result;
 1401|  1.32k|  return true;
 1402|  1.46k|}
mg_http_var:
 1485|  5.44k|struct mg_str mg_http_var(struct mg_str buf, struct mg_str name) {
 1486|  5.44k|  struct mg_str entry, k, v, result = mg_str_n(NULL, 0);
 1487|   216k|  while (mg_span(buf, &entry, &buf, '&')) {
  ------------------
  |  Branch (1487:10): [True: 210k, False: 5.41k]
  ------------------
 1488|   210k|    if (mg_span(entry, &k, &v, '=') && name.len == k.len &&
  ------------------
  |  Branch (1488:9): [True: 209k, False: 1.08k]
  |  Branch (1488:40): [True: 69.6k, False: 140k]
  ------------------
 1489|   210k|        mg_ncasecmp(name.buf, k.buf, k.len) == 0) {
  ------------------
  |  Branch (1489:9): [True: 27, False: 69.5k]
  ------------------
 1490|     27|      result = v;
 1491|     27|      break;
 1492|     27|    }
 1493|   210k|  }
 1494|  5.44k|  return result;
 1495|  5.44k|}
mg_http_get_var:
 1498|  10.8k|                    size_t dst_len) {
 1499|  10.8k|  int len;
 1500|  10.8k|  if (dst != NULL && dst_len > 0) {
  ------------------
  |  Branch (1500:7): [True: 5.44k, False: 5.44k]
  |  Branch (1500:22): [True: 5.44k, False: 0]
  ------------------
 1501|  5.44k|    dst[0] = '\0';  // If destination buffer is valid, always nul-terminate it
 1502|  5.44k|  }
 1503|  10.8k|  if (dst == NULL || dst_len == 0) {
  ------------------
  |  Branch (1503:7): [True: 5.44k, False: 5.44k]
  |  Branch (1503:22): [True: 0, False: 5.44k]
  ------------------
 1504|  5.44k|    len = -2;  // Bad destination
 1505|  5.44k|  } else if (buf->buf == NULL || name == NULL || buf->len == 0) {
  ------------------
  |  Branch (1505:14): [True: 0, False: 5.44k]
  |  Branch (1505:34): [True: 0, False: 5.44k]
  |  Branch (1505:50): [True: 0, False: 5.44k]
  ------------------
 1506|      0|    len = -1;  // Bad source
 1507|  5.44k|  } else {
 1508|  5.44k|    struct mg_str v = mg_http_var(*buf, mg_str(name));
  ------------------
  |  |  913|  5.44k|#define mg_str(s) mg_str_s(s)
  ------------------
 1509|  5.44k|    if (v.buf == NULL) {
  ------------------
  |  Branch (1509:9): [True: 5.41k, False: 27]
  ------------------
 1510|  5.41k|      len = -4;  // Name does not exist
 1511|  5.41k|    } else {
 1512|     27|      len = mg_url_decode(v.buf, v.len, dst, dst_len, 1);
 1513|     27|      if (len < 0) len = -3;  // Failed to decode
  ------------------
  |  Branch (1513:11): [True: 10, False: 17]
  ------------------
 1514|     27|    }
 1515|  5.44k|  }
 1516|  10.8k|  return len;
 1517|  10.8k|}
mg_url_decode:
 1525|   353k|                  int is_form_url_encoded) {
 1526|   353k|  size_t i, j;
 1527|  4.96M|  for (i = j = 0; i < src_len && j + 1 < dst_len; i++, j++) {
  ------------------
  |  Branch (1527:19): [True: 4.61M, False: 342k]
  |  Branch (1527:34): [True: 4.61M, False: 7.12k]
  ------------------
 1528|  4.61M|    if (src[i] == '%') {
  ------------------
  |  Branch (1528:9): [True: 28.4k, False: 4.58M]
  ------------------
 1529|       |      // Use `i + 2 < src_len`, not `i < src_len - 2`, note small src_len
 1530|  28.4k|      if (i + 2 < src_len && isx(src[i + 1]) && isx(src[i + 2])) {
  ------------------
  |  Branch (1530:11): [True: 27.0k, False: 1.39k]
  |  Branch (1530:30): [True: 24.8k, False: 2.18k]
  |  Branch (1530:49): [True: 24.2k, False: 625]
  ------------------
 1531|  24.2k|        mg_str_to_num(mg_str_n(src + i + 1, 2), 16, &dst[j], sizeof(uint8_t));
 1532|  24.2k|        i += 2;
 1533|  24.2k|      } else {
 1534|  4.20k|        return -1;
 1535|  4.20k|      }
 1536|  4.58M|    } else if (is_form_url_encoded && src[i] == '+') {
  ------------------
  |  Branch (1536:16): [True: 420k, False: 4.16M]
  |  Branch (1536:39): [True: 2.42k, False: 418k]
  ------------------
 1537|  2.42k|      dst[j] = ' ';
 1538|  4.58M|    } else {
 1539|  4.58M|      dst[j] = src[i];
 1540|  4.58M|    }
 1541|  4.61M|  }
 1542|   349k|  if (j < dst_len) dst[j] = '\0';  // Null-terminate the destination
  ------------------
  |  Branch (1542:7): [True: 349k, False: 0]
  ------------------
 1543|   349k|  return i >= src_len && j < dst_len ? (int) j : -1;
  ------------------
  |  Branch (1543:10): [True: 342k, False: 7.12k]
  |  Branch (1543:26): [True: 342k, False: 0]
  ------------------
 1544|   353k|}
mg_http_get_request_len:
 1550|   351k|int mg_http_get_request_len(const unsigned char *buf, size_t buf_len) {
 1551|   351k|  size_t i;
 1552|   182M|  for (i = 0; i < buf_len; i++) {
  ------------------
  |  Branch (1552:15): [True: 182M, False: 9.83k]
  ------------------
 1553|   182M|    if (!isok(buf[i])) return -1;
  ------------------
  |  Branch (1553:9): [True: 2.42k, False: 182M]
  ------------------
 1554|   182M|    if ((i > 0 && buf[i] == '\n' && buf[i - 1] == '\n') ||
  ------------------
  |  Branch (1554:10): [True: 182M, False: 345k]
  |  Branch (1554:19): [True: 802k, False: 181M]
  |  Branch (1554:37): [True: 338k, False: 464k]
  ------------------
 1555|   182M|        (i > 3 && buf[i] == '\n' && buf[i - 1] == '\r' && buf[i - 2] == '\n'))
  ------------------
  |  Branch (1555:10): [True: 181M, False: 1.37M]
  |  Branch (1555:19): [True: 215k, False: 180M]
  |  Branch (1555:37): [True: 1.82k, False: 213k]
  |  Branch (1555:59): [True: 630, False: 1.19k]
  ------------------
 1556|   338k|      return (int) i + 1;
 1557|   182M|  }
 1558|  9.83k|  return 0;
 1559|   351k|}
mg_http_get_header:
 1560|  1.08M|struct mg_str *mg_http_get_header(struct mg_http_message *h, const char *name) {
 1561|  1.08M|  size_t i, n = strlen(name), max = sizeof(h->headers) / sizeof(h->headers[0]);
 1562|  1.38M|  for (i = 0; i < max && h->headers[i].name.len > 0; i++) {
  ------------------
  |  Branch (1562:15): [True: 1.38M, False: 1.23k]
  |  Branch (1562:26): [True: 307k, False: 1.07M]
  ------------------
 1563|   307k|    struct mg_str *k = &h->headers[i].name, *v = &h->headers[i].value;
 1564|   307k|    if (n == k->len && mg_ncasecmp(k->buf, name, n) == 0) return v;
  ------------------
  |  Branch (1564:9): [True: 58.1k, False: 249k]
  |  Branch (1564:24): [True: 6.31k, False: 51.8k]
  ------------------
 1565|   307k|  }
 1566|  1.07M|  return NULL;
 1567|  1.08M|}
mg_http_parse:
 1620|   351k|int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
 1621|   351k|  int is_response, req_len = mg_http_get_request_len((unsigned char *) s, len);
 1622|   351k|  const char *end = s == NULL ? NULL : s + req_len, *qs;  // Cannot add to NULL
  ------------------
  |  Branch (1622:21): [True: 5.44k, False: 345k]
  ------------------
 1623|   351k|  const struct mg_str *cl;
 1624|   351k|  size_t n;
 1625|   351k|  bool version_prefix_valid;
 1626|       |
 1627|   351k|  memset(hm, 0, sizeof(*hm));
 1628|   351k|  if (req_len <= 0) return req_len;
  ------------------
  |  Branch (1628:7): [True: 12.2k, False: 338k]
  ------------------
 1629|       |
 1630|   338k|  hm->message.buf = hm->head.buf = (char *) s;
 1631|   338k|  hm->body.buf = (char *) end;
 1632|   338k|  hm->head.len = (size_t) req_len;
 1633|   338k|  hm->message.len = hm->body.len = (size_t) -1;  // Set body length to infinite
 1634|       |
 1635|       |  // Parse request line
 1636|   338k|  hm->method.buf = (char *) s;
 1637|  5.62M|  while (s < end && (n = clen(s, end)) > 0) s += n, hm->method.len += n;
  ------------------
  |  Branch (1637:10): [True: 5.62M, False: 0]
  |  Branch (1637:21): [True: 5.28M, False: 338k]
  ------------------
 1638|   677k|  while (s < end && s[0] == ' ') s++;  // Skip spaces
  ------------------
  |  Branch (1638:10): [True: 677k, False: 0]
  |  Branch (1638:21): [True: 338k, False: 338k]
  ------------------
 1639|   338k|  hm->uri.buf = (char *) s;
 1640|  25.9M|  while (s < end && (n = clen(s, end)) > 0) s += n, hm->uri.len += n;
  ------------------
  |  Branch (1640:10): [True: 25.9M, False: 0]
  |  Branch (1640:21): [True: 25.6M, False: 338k]
  ------------------
 1641|   344k|  while (s < end && s[0] == ' ') s++;  // Skip spaces
  ------------------
  |  Branch (1641:10): [True: 344k, False: 0]
  |  Branch (1641:21): [True: 5.12k, False: 338k]
  ------------------
 1642|   338k|  is_response = hm->method.len > 5 &&
  ------------------
  |  Branch (1642:17): [True: 6.04k, False: 332k]
  ------------------
 1643|   338k|                (mg_ncasecmp(hm->method.buf, "HTTP/", 5) == 0);
  ------------------
  |  Branch (1643:17): [True: 3.35k, False: 2.68k]
  ------------------
 1644|   338k|  if ((s = skiptorn(s, end, &hm->proto)) == NULL) return false;
  ------------------
  |  Branch (1644:7): [True: 327, False: 338k]
  ------------------
 1645|       |  // If we're given a version, check that it is HTTP/x.x
 1646|   338k|  version_prefix_valid = hm->proto.len > 5 &&
  ------------------
  |  Branch (1646:26): [True: 1.34k, False: 337k]
  ------------------
 1647|   338k|                         (mg_ncasecmp(hm->proto.buf, "HTTP/", 5) == 0);
  ------------------
  |  Branch (1647:26): [True: 179, False: 1.16k]
  ------------------
 1648|   338k|  if (!is_response && hm->proto.len > 0 &&
  ------------------
  |  Branch (1648:7): [True: 335k, False: 3.35k]
  |  Branch (1648:23): [True: 609, False: 334k]
  ------------------
 1649|   338k|    (!version_prefix_valid || hm->proto.len != 8 ||
  ------------------
  |  Branch (1649:6): [True: 430, False: 179]
  |  Branch (1649:31): [True: 18, False: 161]
  ------------------
 1650|    609|    (hm->proto.buf[5] < '0' || hm->proto.buf[5] > '9') ||
  ------------------
  |  Branch (1650:6): [True: 19, False: 142]
  |  Branch (1650:32): [True: 9, False: 133]
  ------------------
 1651|    609|    (hm->proto.buf[6] != '.') ||
  ------------------
  |  Branch (1651:5): [True: 21, False: 112]
  ------------------
 1652|    609|    (hm->proto.buf[7] < '0' || hm->proto.buf[7] > '9'))) {
  ------------------
  |  Branch (1652:6): [True: 13, False: 99]
  |  Branch (1652:32): [True: 7, False: 92]
  ------------------
 1653|    517|    return -1;
 1654|    517|  }
 1655|       |
 1656|       |  // If URI contains '?' character, setup query string
 1657|   338k|  if ((qs = (const char *) memchr(hm->uri.buf, '?', hm->uri.len)) != NULL) {
  ------------------
  |  Branch (1657:7): [True: 259, False: 337k]
  ------------------
 1658|    259|    hm->query.buf = (char *) qs + 1;
 1659|    259|    hm->query.len = (size_t) (&hm->uri.buf[hm->uri.len] - (qs + 1));
 1660|    259|    hm->uri.len = (size_t) (qs - hm->uri.buf);
 1661|    259|  }
 1662|       |
 1663|       |  // Sanity check. Allow protocol/reason to be empty
 1664|       |  // Do this check after hm->method.len and hm->uri.len are finalised
 1665|   338k|  if (hm->method.len == 0 || hm->uri.len == 0) return -1;
  ------------------
  |  Branch (1665:7): [True: 125, False: 337k]
  |  Branch (1665:30): [True: 171, False: 337k]
  ------------------
 1666|       |
 1667|   337k|  if (!mg_http_parse_headers(s, end, hm->headers,
  ------------------
  |  Branch (1667:7): [True: 392, False: 337k]
  ------------------
 1668|   337k|                             sizeof(hm->headers) / sizeof(hm->headers[0])))
 1669|    392|    return -1;  // error when parsing
 1670|   337k|  if ((cl = mg_http_get_header(hm, "Content-Length")) != NULL) {
  ------------------
  |  Branch (1670:7): [True: 1.51k, False: 335k]
  ------------------
 1671|  1.51k|    if (mg_to_size_t(*cl, &hm->body.len) == false) return -1;
  ------------------
  |  Branch (1671:9): [True: 190, False: 1.32k]
  ------------------
 1672|  1.32k|    hm->message.len = (size_t) req_len + hm->body.len;
 1673|  1.32k|  }
 1674|       |
 1675|       |  // mg_http_parse() is used to parse both HTTP requests and HTTP
 1676|       |  // responses. If HTTP response does not have Content-Length set, then
 1677|       |  // body is read until socket is closed, i.e. body.len is infinite (~0).
 1678|       |  //
 1679|       |  // For HTTP requests though, according to
 1680|       |  // http://tools.ietf.org/html/rfc7231#section-8.1.3,
 1681|       |  // only POST and PUT methods have defined body semantics.
 1682|       |  // Therefore, if Content-Length is not specified and methods are
 1683|       |  // not one of PUT or POST, set body length to 0.
 1684|       |  //
 1685|       |  // So, if it is HTTP request, and Content-Length is not set,
 1686|       |  // and method is not (PUT or POST) then reset body length to zero.
 1687|   337k|  if (hm->body.len == (size_t) ~0 && !is_response &&
  ------------------
  |  Branch (1687:7): [True: 335k, False: 1.32k]
  |  Branch (1687:38): [True: 332k, False: 3.34k]
  ------------------
 1688|   337k|      mg_strcasecmp(hm->method, mg_str("PUT")) != 0 &&
  ------------------
  |  |  913|   332k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (1688:7): [True: 332k, False: 241]
  ------------------
 1689|   337k|      mg_strcasecmp(hm->method, mg_str("POST")) != 0) {
  ------------------
  |  |  913|   332k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (1689:7): [True: 332k, False: 20]
  ------------------
 1690|   332k|    hm->body.len = 0;
 1691|   332k|    hm->message.len = (size_t) req_len;
 1692|   332k|  }
 1693|       |
 1694|       |  // The 204 (No content) responses also have 0 body length
 1695|   337k|  if (hm->body.len == (size_t) ~0 && is_response &&
  ------------------
  |  Branch (1695:7): [True: 3.61k, False: 333k]
  |  Branch (1695:38): [True: 3.34k, False: 261]
  ------------------
 1696|   337k|      mg_strcasecmp(hm->uri, mg_str("204")) == 0) {
  ------------------
  |  |  913|  3.34k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (1696:7): [True: 3.12k, False: 221]
  ------------------
 1697|  3.12k|    hm->body.len = 0;
 1698|  3.12k|    hm->message.len = (size_t) req_len;
 1699|  3.12k|  }
 1700|   337k|  if (hm->message.len < (size_t) req_len) return -1;  // Overflow protection
  ------------------
  |  Branch (1700:7): [True: 10, False: 337k]
  ------------------
 1701|       |
 1702|   337k|  return req_len;
 1703|   337k|}
mg_http_reply:
 1804|  77.0k|                   const char *fmt, ...) {
 1805|  77.0k|  va_list ap;
 1806|  77.0k|  size_t len;
 1807|  77.0k|  mg_printf(c, "HTTP/1.1 %d %s\r\n%sContent-Length:            \r\n\r\n", code,
 1808|  77.0k|            mg_http_status_code_str(code), headers == NULL ? "" : headers);
  ------------------
  |  Branch (1808:44): [True: 77.0k, False: 70]
  ------------------
 1809|  77.0k|  len = c->send.len;
 1810|  77.0k|  va_start(ap, fmt);
 1811|  77.0k|  mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &ap);
 1812|  77.0k|  va_end(ap);
 1813|  77.0k|  if (c->send.len > 16) {
  ------------------
  |  Branch (1813:7): [True: 77.0k, False: 0]
  ------------------
 1814|  77.0k|    size_t n = mg_snprintf((char *) &c->send.buf[len - 15], 11, "%-10lu",
 1815|  77.0k|                           (unsigned long) (c->send.len - len));
 1816|  77.0k|    c->send.buf[len - 15 + n] = ' ';  // Change ending 0 to space
 1817|  77.0k|  }
 1818|  77.0k|  c->is_resp = 0;
 1819|  77.0k|}
mg_http_serve_file:
 1936|  77.0k|                        const struct mg_http_serve_opts *opts) {
 1937|  77.0k|  char etag[64], tmp[MG_PATH_MAX];
 1938|  77.0k|  struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
  ------------------
  |  Branch (1938:22): [True: 77.0k, False: 0]
  ------------------
 1939|  77.0k|  struct mg_fd *fd = NULL;
 1940|  77.0k|  size_t size = 0;
 1941|  77.0k|  time_t mtime = 0;
 1942|  77.0k|  struct mg_str *inm = NULL;
 1943|  77.0k|  struct mg_str mime = guess_content_type(mg_str(path), opts->mime_types);
  ------------------
  |  |  913|  77.0k|#define mg_str(s) mg_str_s(s)
  ------------------
 1944|  77.0k|  bool gzip = false;
 1945|       |
 1946|  77.0k|  if (path != NULL) {
  ------------------
  |  Branch (1946:7): [True: 77.0k, False: 0]
  ------------------
 1947|       |    // If a browser sends us "Accept-Encoding: gzip", try to open .gz first
 1948|  77.0k|    struct mg_str *ae = mg_http_get_header(hm, "Accept-Encoding");
 1949|  77.0k|    if (ae != NULL) {
  ------------------
  |  Branch (1949:9): [True: 2.88k, False: 74.1k]
  ------------------
 1950|  2.88k|      char *ae_ = mg_mprintf("%.*s", ae->len, ae->buf);
 1951|  2.88k|      if (ae_ != NULL && strstr(ae_, "gzip") != NULL) {
  ------------------
  |  Branch (1951:11): [True: 2.54k, False: 342]
  |  Branch (1951:26): [True: 469, False: 2.07k]
  ------------------
 1952|    469|        mg_snprintf(tmp, sizeof(tmp), "%s.gz", path);
 1953|    469|        fd = mg_fs_open(fs, tmp, MG_FS_READ);
 1954|    469|        if (fd != NULL) gzip = true, path = tmp;
  ------------------
  |  Branch (1954:13): [True: 0, False: 469]
  ------------------
 1955|    469|      }
 1956|  2.88k|      free(ae_);
 1957|  2.88k|    }
 1958|       |    // No luck opening .gz? Open what we've told to open
 1959|  77.0k|    if (fd == NULL) fd = mg_fs_open(fs, path, MG_FS_READ);
  ------------------
  |  Branch (1959:9): [True: 77.0k, False: 0]
  ------------------
 1960|  77.0k|  }
 1961|       |
 1962|       |  // Failed to open, and page404 is configured? Open it, then
 1963|  77.0k|  if (fd == NULL && opts->page404 != NULL) {
  ------------------
  |  Branch (1963:7): [True: 77.0k, False: 0]
  |  Branch (1963:21): [True: 0, False: 77.0k]
  ------------------
 1964|      0|    fd = mg_fs_open(fs, opts->page404, MG_FS_READ);
 1965|      0|    path = opts->page404;
 1966|      0|    mime = guess_content_type(mg_str(path), opts->mime_types);
  ------------------
  |  |  913|      0|#define mg_str(s) mg_str_s(s)
  ------------------
 1967|      0|  }
 1968|       |
 1969|  77.0k|  if (fd == NULL || fs->st(path, &size, &mtime) == 0) {
  ------------------
  |  Branch (1969:7): [True: 77.0k, False: 0]
  |  Branch (1969:21): [True: 0, False: 0]
  ------------------
 1970|  77.0k|    mg_http_reply(c, 404, opts->extra_headers, "Not found\n");
 1971|  77.0k|    mg_fs_close(fd);
 1972|       |    // NOTE: mg_http_etag() call should go first!
 1973|  77.0k|  } else if (mg_http_etag(etag, sizeof(etag), size, mtime) != NULL &&
  ------------------
  |  Branch (1973:14): [True: 0, False: 0]
  ------------------
 1974|      0|             (inm = mg_http_get_header(hm, "If-None-Match")) != NULL &&
  ------------------
  |  Branch (1974:14): [True: 0, False: 0]
  ------------------
 1975|      0|             mg_strcasecmp(*inm, mg_str(etag)) == 0) {
  ------------------
  |  |  913|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (1975:14): [True: 0, False: 0]
  ------------------
 1976|      0|    mg_fs_close(fd);
 1977|      0|    mg_http_reply(c, 304, opts->extra_headers, "");
 1978|      0|  } else {
 1979|      0|    int n, status = 200;
 1980|      0|    char range[100];
 1981|      0|    size_t r1 = 0, r2 = 0, cl = size;
 1982|       |
 1983|       |    // Handle Range header
 1984|      0|    struct mg_str *rh = mg_http_get_header(hm, "Range");
 1985|      0|    range[0] = '\0';
 1986|      0|    if (rh != NULL && (n = getrange(rh, &r1, &r2)) > 0) {
  ------------------
  |  Branch (1986:9): [True: 0, False: 0]
  |  Branch (1986:23): [True: 0, False: 0]
  ------------------
 1987|       |      // If range is specified like "400-", set second limit to content len
 1988|      0|      if (n == 1) r2 = cl - 1;
  ------------------
  |  Branch (1988:11): [True: 0, False: 0]
  ------------------
 1989|      0|      if (r1 > r2 || r2 >= cl) {
  ------------------
  |  Branch (1989:11): [True: 0, False: 0]
  |  Branch (1989:22): [True: 0, False: 0]
  ------------------
 1990|      0|        status = 416;
 1991|      0|        cl = 0;
 1992|      0|        mg_snprintf(range, sizeof(range), "Content-Range: bytes */%lld\r\n",
 1993|      0|                    (int64_t) size);
 1994|      0|      } else {
 1995|      0|        status = 206;
 1996|      0|        cl = r2 - r1 + 1;
 1997|      0|        mg_snprintf(range, sizeof(range),
 1998|      0|                    "Content-Range: bytes %llu-%llu/%llu\r\n", (uint64_t) r1,
 1999|      0|                    (uint64_t) (r1 + cl - 1), (uint64_t) size);
 2000|      0|        fs->sk(fd->fd, r1);
 2001|      0|      }
 2002|      0|    }
 2003|      0|    mg_printf(c,
 2004|      0|              "HTTP/1.1 %d %s\r\n"
 2005|      0|              "Content-Type: %.*s\r\n"
 2006|      0|              "Etag: %s\r\n"
 2007|      0|              "Content-Length: %llu\r\n"
 2008|      0|              "%s%s%s\r\n",
 2009|      0|              status, mg_http_status_code_str(status), (int) mime.len, mime.buf,
 2010|      0|              etag, (uint64_t) cl, gzip ? "Content-Encoding: gzip\r\n" : "",
  ------------------
  |  Branch (2010:36): [True: 0, False: 0]
  ------------------
 2011|      0|              range, opts->extra_headers ? opts->extra_headers : "");
  ------------------
  |  Branch (2011:22): [True: 0, False: 0]
  ------------------
 2012|      0|    if (mg_strcasecmp(hm->method, mg_str("HEAD")) == 0) {
  ------------------
  |  |  913|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (2012:9): [True: 0, False: 0]
  ------------------
 2013|      0|      c->is_resp = 0;
 2014|      0|      mg_fs_close(fd);
 2015|      0|    } else {
 2016|       |      // Track to-be-sent content length at the end of c->data, aligned
 2017|      0|      size_t *clp = (size_t *) &c->data[(sizeof(c->data) - sizeof(size_t)) /
 2018|      0|                                        sizeof(size_t) * sizeof(size_t)];
 2019|      0|      c->pfn = static_cb;
 2020|      0|      c->pfn_data = fd;
 2021|      0|      *clp = cl;
 2022|      0|    }
 2023|      0|  }
 2024|  77.0k|}
mg_http_serve_dir:
 2219|   333k|                       const struct mg_http_serve_opts *opts) {
 2220|   333k|  char path[MG_PATH_MAX];
 2221|   333k|  const char *sp = opts->ssi_pattern;
 2222|   333k|  int flags = uri_to_path(c, hm, opts, path, sizeof(path));
 2223|   333k|  if (flags < 0) {
  ------------------
  |  Branch (2223:7): [True: 4.36k, False: 329k]
  ------------------
 2224|       |    // Do nothing: the response has already been sent by uri_to_path()
 2225|   329k|  } else if (flags & MG_FS_DIR) {
  ------------------
  |  Branch (2225:14): [True: 252k, False: 77.0k]
  ------------------
 2226|   252k|#if MG_ENABLE_DIRLIST
 2227|   252k|    listdir(c, hm, opts, path);
 2228|       |#else
 2229|       |    mg_http_reply(c, 403, "", "Forbidden\n");
 2230|       |#endif
 2231|   252k|  } else if (flags && sp != NULL && mg_match(mg_str(path), mg_str(sp), NULL)) {
  ------------------
  |  |  913|      0|#define mg_str(s) mg_str_s(s)
  ------------------
                } else if (flags && sp != NULL && mg_match(mg_str(path), mg_str(sp), NULL)) {
  ------------------
  |  |  913|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (2231:14): [True: 0, False: 77.0k]
  |  Branch (2231:23): [True: 0, False: 0]
  |  Branch (2231:37): [True: 0, False: 0]
  ------------------
 2232|      0|    mg_http_serve_ssi(c, opts->root_dir, path);
 2233|  77.0k|  } else {
 2234|  77.0k|    mg_http_serve_file(c, hm, path, opts);
 2235|  77.0k|  }
 2236|   333k|}
mg_url_encode:
 2243|  3.27M|size_t mg_url_encode(const char *s, size_t sl, char *buf, size_t len) {
 2244|  3.27M|  size_t i, n = 0;
 2245|  34.5M|  for (i = 0; i < sl; i++) {
  ------------------
  |  Branch (2245:15): [True: 31.2M, False: 3.27M]
  ------------------
 2246|  31.2M|    int c = *(unsigned char *) &s[i];
 2247|  31.2M|    if (n + 4 >= len) return 0;
  ------------------
  |  Branch (2247:9): [True: 0, False: 31.2M]
  ------------------
 2248|  31.2M|    if (mg_is_url_safe(c)) {
  ------------------
  |  Branch (2248:9): [True: 31.2M, False: 0]
  ------------------
 2249|  31.2M|      buf[n++] = s[i];
 2250|  31.2M|    } else {
 2251|      0|      mg_snprintf(&buf[n], 4, "%%%M", mg_print_hex, 1, &s[i]);
 2252|      0|      n += 3;
 2253|      0|    }
 2254|  31.2M|  }
 2255|  3.27M|  if (len > 0 && n < len - 1) buf[n] = '\0';  // Null-terminate the destination
  ------------------
  |  Branch (2255:7): [True: 3.27M, False: 0]
  |  Branch (2255:18): [True: 3.27M, False: 0]
  ------------------
 2256|  3.27M|  if (len > 0) buf[len - 1] = '\0';           // Always.
  ------------------
  |  Branch (2256:7): [True: 3.27M, False: 0]
  ------------------
 2257|  3.27M|  return n;
 2258|  3.27M|}
mg_http_status:
 2349|  7.57k|int mg_http_status(const struct mg_http_message *hm) {
 2350|  7.57k|  return atoi(hm->uri.buf);
 2351|  7.57k|}
mg_http_connect:
 2510|  5.44k|                                      mg_event_handler_t fn, void *fn_data) {
 2511|  5.44k|  struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
 2512|  5.44k|  if (c != NULL) c->pfn = http_cb;
  ------------------
  |  Branch (2512:7): [True: 5.44k, False: 0]
  ------------------
 2513|  5.44k|  return c;
 2514|  5.44k|}
mg_iobuf_resize:
 2535|  70.5k|int mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) {
 2536|  70.5k|  int ok = 1;
 2537|  70.5k|  new_size = roundup(new_size, io->align);
 2538|  70.5k|  if (new_size == 0) {
  ------------------
  |  Branch (2538:7): [True: 21.7k, False: 48.8k]
  ------------------
 2539|  21.7k|    mg_bzero(io->buf, io->size);
 2540|  21.7k|    free(io->buf);
 2541|  21.7k|    io->buf = NULL;
 2542|  21.7k|    io->len = io->size = 0;
 2543|  48.8k|  } else if (new_size != io->size) {
  ------------------
  |  Branch (2543:14): [True: 48.8k, False: 0]
  ------------------
 2544|       |    // NOTE(lsm): do not use realloc here. Use calloc/free only, to ease the
 2545|       |    // porting to some obscure platforms like FreeRTOS
 2546|  48.8k|    void *p = calloc(1, new_size);
 2547|  48.8k|    if (p != NULL) {
  ------------------
  |  Branch (2547:9): [True: 48.8k, False: 0]
  ------------------
 2548|  48.8k|      size_t len = new_size < io->len ? new_size : io->len;
  ------------------
  |  Branch (2548:20): [True: 0, False: 48.8k]
  ------------------
 2549|  48.8k|      if (len > 0 && io->buf != NULL) memmove(p, io->buf, len);
  ------------------
  |  Branch (2549:11): [True: 38.8k, False: 9.97k]
  |  Branch (2549:22): [True: 38.8k, False: 0]
  ------------------
 2550|  48.8k|      mg_bzero(io->buf, io->size);
 2551|  48.8k|      free(io->buf);
 2552|  48.8k|      io->buf = (unsigned char *) p;
 2553|  48.8k|      io->size = new_size;
 2554|  48.8k|    } else {
 2555|      0|      ok = 0;
 2556|      0|      MG_ERROR(("%lld->%lld", (uint64_t) io->size, (uint64_t) new_size));
  ------------------
  |  | 1014|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2557|      0|    }
 2558|  48.8k|  }
 2559|  70.5k|  return ok;
 2560|  70.5k|}
mg_iobuf_add:
 2570|  5.44k|                    size_t len) {
 2571|  5.44k|  size_t new_size = roundup(io->len + len, io->align);
 2572|  5.44k|  mg_iobuf_resize(io, new_size);      // Attempt to resize
 2573|  5.44k|  if (new_size != io->size) len = 0;  // Resize failure, append nothing
  ------------------
  |  Branch (2573:7): [True: 0, False: 5.44k]
  ------------------
 2574|  5.44k|  if (ofs < io->len) memmove(io->buf + ofs + len, io->buf + ofs, io->len - ofs);
  ------------------
  |  Branch (2574:7): [True: 0, False: 5.44k]
  ------------------
 2575|  5.44k|  if (buf != NULL) memmove(io->buf + ofs, buf, len);
  ------------------
  |  Branch (2575:7): [True: 5.44k, False: 0]
  ------------------
 2576|  5.44k|  if (ofs > io->len) io->len += ofs - io->len;
  ------------------
  |  Branch (2576:7): [True: 0, False: 5.44k]
  ------------------
 2577|  5.44k|  io->len += len;
 2578|  5.44k|  return len;
 2579|  5.44k|}
mg_iobuf_del:
 2581|  1.72k|size_t mg_iobuf_del(struct mg_iobuf *io, size_t ofs, size_t len) {
 2582|  1.72k|  if (ofs > io->len) ofs = io->len;
  ------------------
  |  Branch (2582:7): [True: 0, False: 1.72k]
  ------------------
 2583|  1.72k|  if (ofs + len > io->len) len = io->len - ofs;
  ------------------
  |  Branch (2583:7): [True: 23, False: 1.70k]
  ------------------
 2584|  1.72k|  if (io->buf) memmove(io->buf + ofs, io->buf + ofs + len, io->len - ofs - len);
  ------------------
  |  Branch (2584:7): [True: 1.72k, False: 0]
  ------------------
 2585|  1.72k|  if (io->buf) mg_bzero(io->buf + io->len - len, len);
  ------------------
  |  Branch (2585:7): [True: 1.72k, False: 0]
  ------------------
 2586|  1.72k|  io->len -= len;
 2587|  1.72k|  return len;
 2588|  1.72k|}
mg_iobuf_free:
 2590|  21.7k|void mg_iobuf_free(struct mg_iobuf *io) {
 2591|  21.7k|  mg_iobuf_resize(io, 0);
 2592|  21.7k|}
mg_json_get:
 2722|  16.3k|int mg_json_get(struct mg_str json, const char *path, int *toklen) {
 2723|  16.3k|  const char *s = json.buf;
 2724|  16.3k|  int len = (int) json.len;
 2725|  16.3k|  enum { S_VALUE, S_KEY, S_COLON, S_COMMA_OR_EOO } expecting = S_VALUE;
 2726|  16.3k|  unsigned char nesting[MG_JSON_MAX_DEPTH];
 2727|  16.3k|  int i = 0;             // Current offset in `s`
 2728|  16.3k|  int j = 0;             // Offset in `s` we're looking for (return value)
 2729|  16.3k|  int depth = 0;         // Current depth (nesting level)
 2730|  16.3k|  int ed = 0;            // Expected depth
 2731|  16.3k|  int pos = 1;           // Current position in `path`
 2732|  16.3k|  int ci = -1, ei = -1;  // Current and expected index in array
 2733|       |
 2734|  16.3k|  if (toklen) *toklen = 0;
  ------------------
  |  Branch (2734:7): [True: 16.3k, False: 0]
  ------------------
 2735|  16.3k|  if (path[0] != '$') return MG_JSON_INVALID;
  ------------------
  |  Branch (2735:7): [True: 0, False: 16.3k]
  ------------------
 2736|       |
 2737|  16.3k|#define MG_CHECKRET(x)                                  \
 2738|  16.3k|  do {                                                  \
 2739|  16.3k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
 2740|  16.3k|      if (toklen) *toklen = i - j + 1;                  \
 2741|  16.3k|      return j;                                         \
 2742|  16.3k|    }                                                   \
 2743|  16.3k|  } while (0)
 2744|       |
 2745|       |// In the ascii table, the distance between `[` and `]` is 2.
 2746|       |// Ditto for `{` and `}`. Hence +2 in the code below.
 2747|  16.3k|#define MG_EOO(x)                                            \
 2748|  16.3k|  do {                                                       \
 2749|  16.3k|    if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND;   \
 2750|  16.3k|    if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
 2751|  16.3k|    depth--;                                                 \
 2752|  16.3k|    MG_CHECKRET(x);                                          \
 2753|  16.3k|  } while (0)
 2754|       |
 2755|  1.01M|  for (i = 0; i < len; i++) {
  ------------------
  |  Branch (2755:15): [True: 1.01M, False: 1.12k]
  ------------------
 2756|  1.01M|    unsigned char c = ((unsigned char *) s)[i];
 2757|  1.01M|    if (c == ' ' || c == '\t' || c == '\n' || c == '\r') continue;
  ------------------
  |  Branch (2757:9): [True: 1.98k, False: 1.01M]
  |  Branch (2757:21): [True: 275, False: 1.01M]
  |  Branch (2757:34): [True: 598, False: 1.01M]
  |  Branch (2757:47): [True: 616, False: 1.01M]
  ------------------
 2758|  1.01M|    switch (expecting) {
  ------------------
  |  Branch (2758:13): [True: 0, False: 1.01M]
  ------------------
 2759|   484k|      case S_VALUE:
  ------------------
  |  Branch (2759:7): [True: 484k, False: 525k]
  ------------------
 2760|       |        // p("V %s [%.*s] %d %d %d %d\n", path, pos, path, depth, ed, ci, ei);
 2761|   484k|        if (depth == ed) j = i;
  ------------------
  |  Branch (2761:13): [True: 22.5k, False: 462k]
  ------------------
 2762|   484k|        if (c == '{') {
  ------------------
  |  Branch (2762:13): [True: 13.8k, False: 470k]
  ------------------
 2763|  13.8k|          if (depth >= (int) sizeof(nesting)) return MG_JSON_TOO_DEEP;
  ------------------
  |  Branch (2763:15): [True: 14, False: 13.8k]
  ------------------
 2764|  13.8k|          if (depth == ed && path[pos] == '.' && ci == ei) {
  ------------------
  |  Branch (2764:15): [True: 1.70k, False: 12.1k]
  |  Branch (2764:30): [True: 299, False: 1.41k]
  |  Branch (2764:50): [True: 299, False: 0]
  ------------------
 2765|       |            // If we start the object, reset array indices
 2766|    299|            ed++, pos++, ci = ei = -1;
 2767|    299|          }
 2768|  13.8k|          nesting[depth++] = c;
 2769|  13.8k|          expecting = S_KEY;
 2770|  13.8k|          break;
 2771|   470k|        } else if (c == '[') {
  ------------------
  |  Branch (2771:20): [True: 19.7k, False: 451k]
  ------------------
 2772|  19.7k|          if (depth >= (int) sizeof(nesting)) return MG_JSON_TOO_DEEP;
  ------------------
  |  Branch (2772:15): [True: 14, False: 19.7k]
  ------------------
 2773|  19.7k|          if (depth == ed && path[pos] == '[' && ei == ci) {
  ------------------
  |  Branch (2773:15): [True: 4.55k, False: 15.1k]
  |  Branch (2773:30): [True: 420, False: 4.13k]
  |  Branch (2773:50): [True: 420, False: 0]
  ------------------
 2774|    420|            ed++, pos++, ci = 0;
 2775|    840|            for (ei = 0; path[pos] != ']' && path[pos] != '\0'; pos++) {
  ------------------
  |  Branch (2775:26): [True: 420, False: 420]
  |  Branch (2775:46): [True: 420, False: 0]
  ------------------
 2776|    420|              ei *= 10;
 2777|    420|              ei += path[pos] - '0';
 2778|    420|            }
 2779|    420|            if (path[pos] != 0) pos++;
  ------------------
  |  Branch (2779:17): [True: 420, False: 0]
  ------------------
 2780|    420|          }
 2781|  19.7k|          nesting[depth++] = c;
 2782|  19.7k|          break;
 2783|   451k|        } else if (c == ']' && depth > 0) {  // Empty array
  ------------------
  |  Branch (2783:20): [True: 8.25k, False: 442k]
  |  Branch (2783:32): [True: 8.01k, False: 240]
  ------------------
 2784|  8.01k|          MG_EOO(']');
  ------------------
  |  | 2748|  8.01k|  do {                                                       \
  |  | 2749|  8.01k|    if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND;   \
  |  |  ------------------
  |  |  |  Branch (2749:9): [True: 5, False: 8.00k]
  |  |  |  Branch (2749:24): [True: 0, False: 5]
  |  |  ------------------
  |  | 2750|  8.01k|    if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
  |  |  ------------------
  |  |  |  Branch (2750:9): [True: 8, False: 8.00k]
  |  |  ------------------
  |  | 2751|  8.01k|    depth--;                                                 \
  |  | 2752|  8.00k|    MG_CHECKRET(x);                                          \
  |  |  ------------------
  |  |  |  | 2738|  8.00k|  do {                                                  \
  |  |  |  | 2739|  8.00k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (2739:9): [True: 1.74k, False: 6.26k]
  |  |  |  |  |  Branch (2739:24): [True: 24, False: 1.71k]
  |  |  |  |  |  Branch (2739:45): [True: 24, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 2740|     24|      if (toklen) *toklen = i - j + 1;                  \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (2740:11): [True: 24, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 2741|     24|      return j;                                         \
  |  |  |  | 2742|     24|    }                                                   \
  |  |  |  | 2743|  8.00k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (2743:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 2753|  8.00k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2753:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
 2785|   443k|        } else if (c == 't' && i + 3 < len && memcmp(&s[i], "true", 4) == 0) {
  ------------------
  |  Branch (2785:20): [True: 3.62k, False: 439k]
  |  Branch (2785:32): [True: 3.60k, False: 20]
  |  Branch (2785:47): [True: 3.18k, False: 418]
  ------------------
 2786|  3.18k|          i += 3;
 2787|   439k|        } else if (c == 'n' && i + 3 < len && memcmp(&s[i], "null", 4) == 0) {
  ------------------
  |  Branch (2787:20): [True: 23.1k, False: 416k]
  |  Branch (2787:32): [True: 23.1k, False: 21]
  |  Branch (2787:47): [True: 22.9k, False: 173]
  ------------------
 2788|  22.9k|          i += 3;
 2789|   416k|        } else if (c == 'f' && i + 4 < len && memcmp(&s[i], "false", 5) == 0) {
  ------------------
  |  Branch (2789:20): [True: 8.04k, False: 408k]
  |  Branch (2789:32): [True: 8.03k, False: 14]
  |  Branch (2789:47): [True: 7.81k, False: 218]
  ------------------
 2790|  7.81k|          i += 4;
 2791|   409k|        } else if (c == '-' || ((c >= '0' && c <= '9'))) {
  ------------------
  |  Branch (2791:20): [True: 184k, False: 224k]
  |  Branch (2791:34): [True: 218k, False: 5.73k]
  |  Branch (2791:46): [True: 210k, False: 7.46k]
  ------------------
 2792|   395k|          int numlen = 0;
 2793|   395k|          mg_atod(&s[i], len - i, &numlen);
 2794|   395k|          i += numlen - 1;
 2795|   395k|        } else if (c == '"') {
  ------------------
  |  Branch (2795:20): [True: 2.18k, False: 11.0k]
  ------------------
 2796|  2.18k|          int n = mg_pass_string(&s[i + 1], len - i - 1);
 2797|  2.18k|          if (n < 0) return n;
  ------------------
  |  Branch (2797:15): [True: 341, False: 1.84k]
  ------------------
 2798|  1.84k|          i += n + 1;
 2799|  11.0k|        } else {
 2800|  11.0k|          return MG_JSON_INVALID;
 2801|  11.0k|        }
 2802|   439k|        MG_CHECKRET('V');
  ------------------
  |  | 2738|   439k|  do {                                                  \
  |  | 2739|   439k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
  |  |  ------------------
  |  |  |  Branch (2739:9): [True: 6.90k, False: 432k]
  |  |  |  Branch (2739:24): [True: 1.14k, False: 5.75k]
  |  |  |  Branch (2739:45): [True: 1.14k, False: 0]
  |  |  ------------------
  |  | 2740|  1.14k|      if (toklen) *toklen = i - j + 1;                  \
  |  |  ------------------
  |  |  |  Branch (2740:11): [True: 1.14k, False: 0]
  |  |  ------------------
  |  | 2741|  1.14k|      return j;                                         \
  |  | 2742|  1.14k|    }                                                   \
  |  | 2743|   439k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2743:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
 2803|   438k|        if (depth == ed && ei >= 0) ci++;
  ------------------
  |  Branch (2803:13): [True: 5.75k, False: 432k]
  |  Branch (2803:28): [True: 0, False: 5.75k]
  ------------------
 2804|   438k|        expecting = S_COMMA_OR_EOO;
 2805|   438k|        break;
 2806|       |
 2807|  39.5k|      case S_KEY:
  ------------------
  |  Branch (2807:7): [True: 39.5k, False: 970k]
  ------------------
 2808|  39.5k|        if (c == '"') {
  ------------------
  |  Branch (2808:13): [True: 28.4k, False: 11.1k]
  ------------------
 2809|  28.4k|          int n = mg_pass_string(&s[i + 1], len - i - 1);
 2810|  28.4k|          if (n < 0) return n;
  ------------------
  |  Branch (2810:15): [True: 271, False: 28.1k]
  ------------------
 2811|  28.1k|          if (i + 1 + n >= len) return MG_JSON_NOT_FOUND;
  ------------------
  |  Branch (2811:15): [True: 0, False: 28.1k]
  ------------------
 2812|  28.1k|          if (depth < ed) return MG_JSON_NOT_FOUND;
  ------------------
  |  Branch (2812:15): [True: 1, False: 28.1k]
  ------------------
 2813|  28.1k|          if (depth == ed && path[pos - 1] != '.') return MG_JSON_NOT_FOUND;
  ------------------
  |  Branch (2813:15): [True: 5.98k, False: 22.1k]
  |  Branch (2813:30): [True: 1, False: 5.97k]
  ------------------
 2814|       |          // printf("K %s [%.*s] [%.*s] %d %d %d %d %d\n", path, pos, path, n,
 2815|       |          //        &s[i + 1], n, depth, ed, ci, ei);
 2816|       |          //  NOTE(cpq): in the check sequence below is important.
 2817|       |          //  strncmp() must go first: it fails fast if the remaining length
 2818|       |          //  of the path is smaller than `n`.
 2819|  28.1k|          if (depth == ed && path[pos - 1] == '.' &&
  ------------------
  |  Branch (2819:15): [True: 5.97k, False: 22.1k]
  |  Branch (2819:30): [True: 5.97k, False: 0]
  ------------------
 2820|  28.1k|              strncmp(&s[i + 1], &path[pos], (size_t) n) == 0 &&
  ------------------
  |  Branch (2820:15): [True: 3.51k, False: 2.46k]
  ------------------
 2821|  28.1k|              (path[pos + n] == '\0' || path[pos + n] == '.' ||
  ------------------
  |  Branch (2821:16): [True: 3, False: 3.51k]
  |  Branch (2821:41): [True: 8, False: 3.50k]
  ------------------
 2822|  3.51k|               path[pos + n] == '[')) {
  ------------------
  |  Branch (2822:16): [True: 0, False: 3.50k]
  ------------------
 2823|     11|            pos += n;
 2824|     11|          }
 2825|  28.1k|          i += n + 1;
 2826|  28.1k|          expecting = S_COLON;
 2827|  28.1k|        } else if (c == '}') {  // Empty object
  ------------------
  |  Branch (2827:20): [True: 11.0k, False: 116]
  ------------------
 2828|  11.0k|          MG_EOO('}');
  ------------------
  |  | 2748|  11.0k|  do {                                                       \
  |  | 2749|  11.0k|    if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND;   \
  |  |  ------------------
  |  |  |  Branch (2749:9): [True: 15, False: 11.0k]
  |  |  |  Branch (2749:24): [True: 0, False: 15]
  |  |  ------------------
  |  | 2750|  11.0k|    if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
  |  |  ------------------
  |  |  |  Branch (2750:9): [True: 0, False: 11.0k]
  |  |  ------------------
  |  | 2751|  11.0k|    depth--;                                                 \
  |  | 2752|  11.0k|    MG_CHECKRET(x);                                          \
  |  |  ------------------
  |  |  |  | 2738|  11.0k|  do {                                                  \
  |  |  |  | 2739|  11.0k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (2739:9): [True: 809, False: 10.2k]
  |  |  |  |  |  Branch (2739:24): [True: 19, False: 790]
  |  |  |  |  |  Branch (2739:45): [True: 19, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 2740|     19|      if (toklen) *toklen = i - j + 1;                  \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (2740:11): [True: 19, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 2741|     19|      return j;                                         \
  |  |  |  | 2742|     19|    }                                                   \
  |  |  |  | 2743|  11.0k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (2743:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 2753|  11.0k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2753:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
 2829|  11.0k|          expecting = S_COMMA_OR_EOO;
 2830|  11.0k|          if (depth == ed && ei >= 0) ci++;
  ------------------
  |  Branch (2830:15): [True: 790, False: 10.2k]
  |  Branch (2830:30): [True: 0, False: 790]
  ------------------
 2831|  11.0k|        } else {
 2832|    116|          return MG_JSON_INVALID;
 2833|    116|        }
 2834|  39.1k|        break;
 2835|       |
 2836|  39.1k|      case S_COLON:
  ------------------
  |  Branch (2836:7): [True: 27.9k, False: 982k]
  ------------------
 2837|  27.9k|        if (c == ':') {
  ------------------
  |  Branch (2837:13): [True: 27.8k, False: 107]
  ------------------
 2838|  27.8k|          expecting = S_VALUE;
 2839|  27.8k|        } else {
 2840|    107|          return MG_JSON_INVALID;
 2841|    107|        }
 2842|  27.8k|        break;
 2843|       |
 2844|   457k|      case S_COMMA_OR_EOO:
  ------------------
  |  Branch (2844:7): [True: 457k, False: 552k]
  ------------------
 2845|   457k|        if (depth <= 0) {
  ------------------
  |  Branch (2845:13): [True: 1.75k, False: 456k]
  ------------------
 2846|  1.75k|          return MG_JSON_INVALID;
 2847|   456k|        } else if (c == ',') {
  ------------------
  |  Branch (2847:20): [True: 446k, False: 9.46k]
  ------------------
 2848|   446k|          expecting = (nesting[depth - 1] == '{') ? S_KEY : S_VALUE;
  ------------------
  |  Branch (2848:23): [True: 25.7k, False: 420k]
  ------------------
 2849|   446k|        } else if (c == ']' || c == '}') {
  ------------------
  |  Branch (2849:20): [True: 7.89k, False: 1.56k]
  |  Branch (2849:32): [True: 1.27k, False: 296]
  ------------------
 2850|  9.17k|          if (depth == ed && c == '}' && path[pos - 1] == '.')
  ------------------
  |  Branch (2850:15): [True: 8, False: 9.16k]
  |  Branch (2850:30): [True: 6, False: 2]
  |  Branch (2850:42): [True: 5, False: 1]
  ------------------
 2851|      5|            return MG_JSON_NOT_FOUND;
 2852|  9.16k|          if (depth == ed && c == ']' && path[pos - 1] == ',')
  ------------------
  |  Branch (2852:15): [True: 3, False: 9.16k]
  |  Branch (2852:30): [True: 2, False: 1]
  |  Branch (2852:42): [True: 0, False: 2]
  ------------------
 2853|      0|            return MG_JSON_NOT_FOUND;
 2854|  9.16k|          MG_EOO('O');
  ------------------
  |  | 2748|  9.16k|  do {                                                       \
  |  | 2749|  9.16k|    if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND;   \
  |  |  ------------------
  |  |  |  Branch (2749:9): [True: 3, False: 9.16k]
  |  |  |  Branch (2749:24): [True: 0, False: 3]
  |  |  ------------------
  |  | 2750|  9.16k|    if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
  |  |  ------------------
  |  |  |  Branch (2750:9): [True: 19, False: 9.14k]
  |  |  ------------------
  |  | 2751|  9.16k|    depth--;                                                 \
  |  | 2752|  9.14k|    MG_CHECKRET(x);                                          \
  |  |  ------------------
  |  |  |  | 2738|  9.14k|  do {                                                  \
  |  |  |  | 2739|  9.14k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (2739:9): [True: 1.41k, False: 7.73k]
  |  |  |  |  |  Branch (2739:24): [True: 50, False: 1.36k]
  |  |  |  |  |  Branch (2739:45): [True: 50, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 2740|     50|      if (toklen) *toklen = i - j + 1;                  \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (2740:11): [True: 50, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 2741|     50|      return j;                                         \
  |  |  |  | 2742|     50|    }                                                   \
  |  |  |  | 2743|  9.14k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (2743:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 2753|  9.14k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2753:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
 2855|  9.09k|          if (depth == ed && ei >= 0) ci++;
  ------------------
  |  Branch (2855:15): [True: 1.36k, False: 7.73k]
  |  Branch (2855:30): [True: 0, False: 1.36k]
  ------------------
 2856|  9.09k|        } else {
 2857|    296|          return MG_JSON_INVALID;
 2858|    296|        }
 2859|   455k|        break;
 2860|  1.01M|    }
 2861|  1.01M|  }
 2862|  1.12k|  return MG_JSON_NOT_FOUND;
 2863|  16.3k|}
mg_hexdump:
 3019|  2.09k|void mg_hexdump(const void *buf, size_t len) {
 3020|  2.09k|  const unsigned char *p = (const unsigned char *) buf;
 3021|  2.09k|  unsigned char ascii[16], alen = 0;
 3022|  2.09k|  size_t i;
 3023|  29.1k|  for (i = 0; i < len; i++) {
  ------------------
  |  Branch (3023:15): [True: 27.0k, False: 2.09k]
  ------------------
 3024|  27.0k|    if ((i % 16) == 0) {
  ------------------
  |  Branch (3024:9): [True: 2.09k, False: 25.0k]
  ------------------
 3025|       |      // Print buffered ascii chars
 3026|  2.09k|      if (i > 0) logs("  ", 2), logs((char *) ascii, 16), logc('\n'), alen = 0;
  ------------------
  |  Branch (3026:11): [True: 0, False: 2.09k]
  ------------------
 3027|       |      // Print hex address, then \t
 3028|  2.09k|      logc(nibble((i >> 12) & 15)), logc(nibble((i >> 8) & 15)),
 3029|  2.09k|          logc(nibble((i >> 4) & 15)), logc('0'), logs("   ", 3);
 3030|  2.09k|    }
 3031|  27.0k|    logc(nibble(p[i] >> 4)), logc(nibble(p[i] & 15));  // Two nibbles, e.g. c5
 3032|  27.0k|    logc(' ');                                         // Space after hex number
 3033|  27.0k|    ascii[alen++] = ISPRINT(p[i]) ? p[i] : '.';        // Add to the ascii buf
  ------------------
  |  | 3018|  27.0k|#define ISPRINT(x) ((x) >= ' ' && (x) <= '~')
  |  |  ------------------
  |  |  |  Branch (3018:21): [True: 19.4k, False: 7.65k]
  |  |  |  Branch (3018:35): [True: 14.1k, False: 5.32k]
  |  |  ------------------
  ------------------
 3034|  27.0k|  }
 3035|  8.56k|  while (alen < 16) logs("   ", 3), ascii[alen++] = ' ';
  ------------------
  |  Branch (3035:10): [True: 6.47k, False: 2.09k]
  ------------------
 3036|  2.09k|  logs("  ", 2), logs((char *) ascii, 16), logc('\n');
 3037|  2.09k|}
mg_mqtt_parse:
 3613|  21.7k|                  struct mg_mqtt_message *m) {
 3614|  21.7k|  uint8_t lc = 0, *p, *end;
 3615|  21.7k|  uint32_t n = 0, len_len = 0;
 3616|       |
 3617|  21.7k|  memset(m, 0, sizeof(*m));
 3618|  21.7k|  m->dgram.buf = (char *) buf;
 3619|  21.7k|  if (len < 2) return MQTT_INCOMPLETE;
  ------------------
  |  Branch (3619:7): [True: 11.1k, False: 10.6k]
  ------------------
 3620|  10.6k|  m->cmd = (uint8_t) (buf[0] >> 4);
 3621|  10.6k|  m->qos = (buf[0] >> 1) & 3;
 3622|       |
 3623|  10.6k|  n = len_len = 0;
 3624|  10.6k|  p = (uint8_t *) buf + 1;
 3625|  12.6k|  while ((size_t) (p - buf) < len) {
  ------------------
  |  Branch (3625:10): [True: 12.5k, False: 118]
  ------------------
 3626|  12.5k|    lc = *((uint8_t *) p++);
 3627|  12.5k|    n += (uint32_t) ((lc & 0x7f) << 7 * len_len);
 3628|  12.5k|    len_len++;
 3629|  12.5k|    if (!(lc & 0x80)) break;
  ------------------
  |  Branch (3629:9): [True: 10.3k, False: 2.20k]
  ------------------
 3630|  2.20k|    if (len_len >= 4) return MQTT_MALFORMED;
  ------------------
  |  Branch (3630:9): [True: 238, False: 1.97k]
  ------------------
 3631|  2.20k|  }
 3632|  10.4k|  end = p + n;
 3633|  10.4k|  if ((lc & 0x80) || (end > buf + len)) return MQTT_INCOMPLETE;
  ------------------
  |  Branch (3633:7): [True: 118, False: 10.3k]
  |  Branch (3633:22): [True: 5.20k, False: 5.10k]
  ------------------
 3634|  5.10k|  m->dgram.len = (size_t) (end - buf);
 3635|       |
 3636|  5.10k|  switch (m->cmd) {
 3637|  1.49k|    case MQTT_CMD_CONNACK:
  ------------------
  |  | 2472|  1.49k|#define MQTT_CMD_CONNACK 2
  ------------------
  |  Branch (3637:5): [True: 1.49k, False: 3.60k]
  ------------------
 3638|  1.49k|      if (end - p < 2) return MQTT_MALFORMED;
  ------------------
  |  Branch (3638:11): [True: 20, False: 1.47k]
  ------------------
 3639|  1.47k|      m->ack = p[1];
 3640|  1.47k|      break;
 3641|    280|    case MQTT_CMD_PUBACK:
  ------------------
  |  | 2474|    280|#define MQTT_CMD_PUBACK 4
  ------------------
  |  Branch (3641:5): [True: 280, False: 4.82k]
  ------------------
 3642|    904|    case MQTT_CMD_PUBREC:
  ------------------
  |  | 2475|    904|#define MQTT_CMD_PUBREC 5
  ------------------
  |  Branch (3642:5): [True: 624, False: 4.47k]
  ------------------
 3643|  1.41k|    case MQTT_CMD_PUBREL:
  ------------------
  |  | 2476|  1.41k|#define MQTT_CMD_PUBREL 6
  ------------------
  |  Branch (3643:5): [True: 512, False: 4.59k]
  ------------------
 3644|  2.18k|    case MQTT_CMD_PUBCOMP:
  ------------------
  |  | 2477|  2.18k|#define MQTT_CMD_PUBCOMP 7
  ------------------
  |  Branch (3644:5): [True: 768, False: 4.33k]
  ------------------
 3645|  2.20k|    case MQTT_CMD_SUBSCRIBE:
  ------------------
  |  | 2478|  2.20k|#define MQTT_CMD_SUBSCRIBE 8
  ------------------
  |  Branch (3645:5): [True: 20, False: 5.08k]
  ------------------
 3646|  2.22k|    case MQTT_CMD_SUBACK:
  ------------------
  |  | 2479|  2.22k|#define MQTT_CMD_SUBACK 9
  ------------------
  |  Branch (3646:5): [True: 16, False: 5.08k]
  ------------------
 3647|  2.25k|    case MQTT_CMD_UNSUBSCRIBE:
  ------------------
  |  | 2480|  2.25k|#define MQTT_CMD_UNSUBSCRIBE 10
  ------------------
  |  Branch (3647:5): [True: 38, False: 5.06k]
  ------------------
 3648|  2.27k|    case MQTT_CMD_UNSUBACK:
  ------------------
  |  | 2481|  2.27k|#define MQTT_CMD_UNSUBACK 11
  ------------------
  |  Branch (3648:5): [True: 12, False: 5.09k]
  ------------------
 3649|  2.27k|      if (p + 2 > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (3649:11): [True: 60, False: 2.21k]
  ------------------
 3650|  2.21k|      m->id = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
 3651|  2.21k|      p += 2;
 3652|  2.21k|      break;
 3653|    962|    case MQTT_CMD_PUBLISH: {
  ------------------
  |  | 2473|    962|#define MQTT_CMD_PUBLISH 3
  ------------------
  |  Branch (3653:5): [True: 962, False: 4.14k]
  ------------------
 3654|    962|      if (p + 2 > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (3654:11): [True: 32, False: 930]
  ------------------
 3655|    930|      m->topic.len = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
 3656|    930|      m->topic.buf = (char *) p + 2;
 3657|    930|      p += 2 + m->topic.len;
 3658|    930|      if (p > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (3658:11): [True: 866, False: 64]
  ------------------
 3659|     64|      if (m->qos > 0) {
  ------------------
  |  Branch (3659:11): [True: 24, False: 40]
  ------------------
 3660|     24|        if (p + 2 > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (3660:13): [True: 6, False: 18]
  ------------------
 3661|     18|        m->id = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
 3662|     18|        p += 2;
 3663|     18|      }
 3664|     58|      if (p > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (3664:11): [True: 0, False: 58]
  ------------------
 3665|     58|      if (version == 5 && p + 2 < end) {
  ------------------
  |  Branch (3665:11): [True: 29, False: 29]
  |  Branch (3665:27): [True: 25, False: 4]
  ------------------
 3666|     25|        len_len =
 3667|     25|            (uint32_t) decode_varint(p, (size_t) (end - p), &m->props_size);
 3668|     25|        if (!len_len) return MQTT_MALFORMED;
  ------------------
  |  Branch (3668:13): [True: 10, False: 15]
  ------------------
 3669|     15|        m->props_start = (size_t) (p + len_len - buf);
 3670|     15|        p += len_len + m->props_size;
 3671|     15|      }
 3672|     48|      if (p > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (3672:11): [True: 2, False: 46]
  ------------------
 3673|     46|      m->data.buf = (char *) p;
 3674|     46|      m->data.len = (size_t) (end - p);
 3675|     46|      break;
 3676|     48|    }
 3677|    372|    default:
  ------------------
  |  Branch (3677:5): [True: 372, False: 4.73k]
  ------------------
 3678|    372|      break;
 3679|  5.10k|  }
 3680|  4.10k|  return MQTT_OK;
 3681|  5.10k|}
mg_vprintf:
 3808|  4.36M|size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list *ap) {
 3809|  4.36M|  size_t old = c->send.len;
 3810|  4.36M|  mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
 3811|  4.36M|  return c->send.len - old;
 3812|  4.36M|}
mg_printf:
 3814|  4.36M|size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
 3815|  4.36M|  size_t len = 0;
 3816|  4.36M|  va_list ap;
 3817|  4.36M|  va_start(ap, fmt);
 3818|  4.36M|  len = mg_vprintf(c, fmt, &ap);
 3819|  4.36M|  va_end(ap);
 3820|  4.36M|  return len;
 3821|  4.36M|}
mg_aton:
 3919|  5.44k|bool mg_aton(struct mg_str str, struct mg_addr *addr) {
 3920|       |  // MG_INFO(("[%.*s]", (int) str.len, str.buf));
 3921|  5.44k|  return mg_atone(str, addr) || mg_atonl(str, addr) || mg_aton4(str, addr) ||
  ------------------
  |  Branch (3921:10): [True: 0, False: 5.44k]
  |  Branch (3921:33): [True: 5.44k, False: 0]
  |  Branch (3921:56): [True: 0, False: 0]
  ------------------
 3922|  5.44k|         mg_aton6(str, addr);
  ------------------
  |  Branch (3922:10): [True: 0, False: 0]
  ------------------
 3923|  5.44k|}
mg_alloc_conn:
 3925|  5.44k|struct mg_connection *mg_alloc_conn(struct mg_mgr *mgr) {
 3926|  5.44k|  struct mg_connection *c =
 3927|  5.44k|      (struct mg_connection *) calloc(1, sizeof(*c) + mgr->extraconnsize);
 3928|  5.44k|  if (c != NULL) {
  ------------------
  |  Branch (3928:7): [True: 5.44k, False: 0]
  ------------------
 3929|  5.44k|    c->mgr = mgr;
 3930|  5.44k|    c->send.align = c->recv.align = c->rtls.align = MG_IO_SIZE;
  ------------------
  |  |    5|  5.44k|#define MG_IO_SIZE (32 * 1024 * 1024)  // Big IO size for fast resizes
  ------------------
 3931|  5.44k|    c->id = ++mgr->nextid;
 3932|  5.44k|    MG_PROF_INIT(c);
 3933|  5.44k|  }
 3934|  5.44k|  return c;
 3935|  5.44k|}
mg_close_conn:
 3937|  5.44k|void mg_close_conn(struct mg_connection *c) {
 3938|  5.44k|  mg_resolve_cancel(c);  // Close any pending DNS query
 3939|  5.44k|  LIST_DELETE(struct mg_connection, &c->mgr->conns, c);
  ------------------
  |  | 1190|  5.44k|  do {                                     \
  |  | 1191|  5.44k|    type_ **h = head_;                     \
  |  | 1192|  5.44k|    while (*h != (elem_)) h = &(*h)->next; \
  |  |  ------------------
  |  |  |  Branch (1192:12): [True: 0, False: 5.44k]
  |  |  ------------------
  |  | 1193|  5.44k|    *h = (elem_)->next;                    \
  |  | 1194|  5.44k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (1194:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
 3940|  5.44k|  if (c == c->mgr->dns4.c) c->mgr->dns4.c = NULL;
  ------------------
  |  Branch (3940:7): [True: 0, False: 5.44k]
  ------------------
 3941|  5.44k|  if (c == c->mgr->dns6.c) c->mgr->dns6.c = NULL;
  ------------------
  |  Branch (3941:7): [True: 0, False: 5.44k]
  ------------------
 3942|       |  // Order of operations is important. `MG_EV_CLOSE` event must be fired
 3943|       |  // before we deallocate received data, see #1331
 3944|  5.44k|  mg_call(c, MG_EV_CLOSE, NULL);
 3945|  5.44k|  MG_DEBUG(("%lu %ld closed", c->id, c->fd));
  ------------------
  |  | 1016|  5.44k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1009|  5.44k|  do {                      \
  |  |  |  | 1010|  5.44k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|  5.44k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3946|  5.44k|  MG_PROF_DUMP(c);
 3947|  5.44k|  MG_PROF_FREE(c);
 3948|       |
 3949|  5.44k|  mg_tls_free(c);
 3950|  5.44k|  mg_iobuf_free(&c->recv);
 3951|  5.44k|  mg_iobuf_free(&c->send);
 3952|  5.44k|  mg_iobuf_free(&c->rtls);
 3953|  5.44k|  mg_bzero((unsigned char *) c, sizeof(*c));
 3954|  5.44k|  free(c);
 3955|  5.44k|}
mg_connect:
 3958|  5.44k|                                 mg_event_handler_t fn, void *fn_data) {
 3959|  5.44k|  struct mg_connection *c = NULL;
 3960|  5.44k|  if (url == NULL || url[0] == '\0') {
  ------------------
  |  Branch (3960:7): [True: 0, False: 5.44k]
  |  Branch (3960:22): [True: 0, False: 5.44k]
  ------------------
 3961|      0|    MG_ERROR(("null url"));
  ------------------
  |  | 1014|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3962|  5.44k|  } else if ((c = mg_alloc_conn(mgr)) == NULL) {
  ------------------
  |  Branch (3962:14): [True: 0, False: 5.44k]
  ------------------
 3963|      0|    MG_ERROR(("OOM"));
  ------------------
  |  | 1014|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3964|  5.44k|  } else {
 3965|  5.44k|    LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
  ------------------
  |  | 1177|  5.44k|  do {                                     \
  |  | 1178|  5.44k|    (elem_)->next = (*head_);              \
  |  | 1179|  5.44k|    *(head_) = (elem_);                    \
  |  | 1180|  5.44k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (1180:12): [Folded - Ignored]
  |  |  ------------------
  ------------------
 3966|  5.44k|    c->is_udp = (strncmp(url, "udp:", 4) == 0);
 3967|  5.44k|    c->fd = (void *) (size_t) MG_INVALID_SOCKET;
  ------------------
  |  |  843|  5.44k|#define MG_INVALID_SOCKET (-1)
  ------------------
 3968|  5.44k|    c->fn = fn;
 3969|  5.44k|    c->is_client = true;
 3970|  5.44k|    c->fn_data = fn_data;
 3971|  5.44k|    MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
  ------------------
  |  | 1016|  5.44k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1009|  5.44k|  do {                      \
  |  |  |  | 1010|  5.44k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|  5.44k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3972|  5.44k|    mg_call(c, MG_EV_OPEN, (void *) url);
 3973|  5.44k|    mg_resolve(c, url);
 3974|  5.44k|  }
 3975|  5.44k|  return c;
 3976|  5.44k|}
mg_mgr_free:
 4033|  5.44k|void mg_mgr_free(struct mg_mgr *mgr) {
 4034|  5.44k|  struct mg_connection *c;
 4035|  5.44k|  struct mg_timer *tmp, *t = mgr->timers;
 4036|  5.44k|  while (t != NULL) tmp = t->next, free(t), t = tmp;
  ------------------
  |  Branch (4036:10): [True: 0, False: 5.44k]
  ------------------
 4037|  5.44k|  mgr->timers = NULL;  // Important. Next call to poll won't touch timers
 4038|  10.8k|  for (c = mgr->conns; c != NULL; c = c->next) c->is_closing = 1;
  ------------------
  |  Branch (4038:24): [True: 5.44k, False: 5.44k]
  ------------------
 4039|  5.44k|  mg_mgr_poll(mgr, 0);
 4040|       |#if MG_ENABLE_FREERTOS_TCP
 4041|       |  FreeRTOS_DeleteSocketSet(mgr->ss);
 4042|       |#endif
 4043|  5.44k|  MG_DEBUG(("All connections closed"));
  ------------------
  |  | 1016|  5.44k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1009|  5.44k|  do {                      \
  |  |  |  | 1010|  5.44k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|  5.44k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4044|  5.44k|#if MG_ENABLE_EPOLL
 4045|  5.44k|  if (mgr->epoll_fd >= 0) close(mgr->epoll_fd), mgr->epoll_fd = -1;
  ------------------
  |  Branch (4045:7): [True: 5.44k, False: 0]
  ------------------
 4046|  5.44k|#endif
 4047|  5.44k|  mg_tls_ctx_free(mgr);
 4048|  5.44k|}
mg_mgr_init:
 4050|  5.44k|void mg_mgr_init(struct mg_mgr *mgr) {
 4051|  5.44k|  memset(mgr, 0, sizeof(*mgr));
 4052|  5.44k|#if MG_ENABLE_EPOLL
 4053|  5.44k|  if ((mgr->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0)
  ------------------
  |  Branch (4053:7): [True: 0, False: 5.44k]
  ------------------
 4054|  5.44k|    MG_ERROR(("epoll_create1 errno %d", errno));
  ------------------
  |  | 1014|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4055|       |#else
 4056|       |  mgr->epoll_fd = -1;
 4057|       |#endif
 4058|       |#if MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK
 4059|       |  // clang-format off
 4060|       |  { WSADATA data; WSAStartup(MAKEWORD(2, 2), &data); }
 4061|       |  // clang-format on
 4062|       |#elif MG_ENABLE_FREERTOS_TCP
 4063|       |  mgr->ss = FreeRTOS_CreateSocketSet();
 4064|       |#elif defined(__unix) || defined(__unix__) || defined(__APPLE__)
 4065|       |  // Ignore SIGPIPE signal, so if client cancels the request, it
 4066|       |  // won't kill the whole process.
 4067|  5.44k|  signal(SIGPIPE, SIG_IGN);
 4068|       |#elif MG_ENABLE_TCPIP_DRIVER_INIT && defined(MG_TCPIP_DRIVER_INIT)
 4069|       |  MG_TCPIP_DRIVER_INIT(mgr);
 4070|       |#endif
 4071|  5.44k|  mgr->pipe = MG_INVALID_SOCKET;
  ------------------
  |  |  843|  5.44k|#define MG_INVALID_SOCKET (-1)
  ------------------
 4072|  5.44k|  mgr->dnstimeout = 3000;
 4073|  5.44k|  mgr->dns4.url = "udp://8.8.8.8:53";
 4074|  5.44k|  mgr->dns6.url = "udp://[2001:4860:4860::8888]:53";
 4075|  5.44k|  mg_tls_ctx_init(mgr);
 4076|  5.44k|}
mg_tcpip_arp_request:
 4270|  5.44k|void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac) {
 4271|  5.44k|  struct eth *eth = (struct eth *) ifp->tx.buf;
 4272|  5.44k|  struct arp *arp = (struct arp *) (eth + 1);
 4273|  5.44k|  memset(eth->dst, 255, sizeof(eth->dst));
 4274|  5.44k|  memcpy(eth->src, ifp->mac, sizeof(eth->src));
 4275|  5.44k|  eth->type = mg_htons(0x806);
  ------------------
  |  | 1113|  5.44k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 4276|  5.44k|  memset(arp, 0, sizeof(*arp));
 4277|  5.44k|  arp->fmt = mg_htons(1), arp->pro = mg_htons(0x800), arp->hlen = 6,
  ------------------
  |  | 1113|  5.44k|#define mg_htons(x) mg_ntohs(x)
  ------------------
                arp->fmt = mg_htons(1), arp->pro = mg_htons(0x800), arp->hlen = 6,
  ------------------
  |  | 1113|  5.44k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 4278|  5.44k|  arp->plen = 4;
 4279|  5.44k|  arp->op = mg_htons(1), arp->tpa = ip, arp->spa = ifp->ip;
  ------------------
  |  | 1113|  5.44k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 4280|  5.44k|  memcpy(arp->sha, ifp->mac, sizeof(arp->sha));
 4281|  5.44k|  if (mac != NULL) memcpy(arp->tha, mac, sizeof(arp->tha));
  ------------------
  |  Branch (4281:7): [True: 0, False: 5.44k]
  ------------------
 4282|  5.44k|  ether_output(ifp, PDIFF(eth, arp + 1));
  ------------------
  |  | 4085|  5.44k|#define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a))))
  ------------------
 4283|  5.44k|}
mg_tcpip_init:
 5103|  5.44k|void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
 5104|       |  // If MAC address is not set, make a random one
 5105|  5.44k|  if (ifp->mac[0] == 0 && ifp->mac[1] == 0 && ifp->mac[2] == 0 &&
  ------------------
  |  Branch (5105:7): [True: 5.44k, False: 0]
  |  Branch (5105:27): [True: 5.44k, False: 0]
  |  Branch (5105:47): [True: 5.44k, False: 0]
  ------------------
 5106|  5.44k|      ifp->mac[3] == 0 && ifp->mac[4] == 0 && ifp->mac[5] == 0) {
  ------------------
  |  Branch (5106:7): [True: 5.44k, False: 0]
  |  Branch (5106:27): [True: 5.44k, False: 0]
  |  Branch (5106:47): [True: 5.44k, False: 0]
  ------------------
 5107|  5.44k|    ifp->mac[0] = 0x02;  // Locally administered, unicast
 5108|  5.44k|    mg_random(&ifp->mac[1], sizeof(ifp->mac) - 1);
 5109|  5.44k|    MG_INFO(("MAC not set. Generated random: %M", mg_print_mac, ifp->mac));
  ------------------
  |  | 1015|  5.44k|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1009|  5.44k|  do {                      \
  |  |  |  | 1010|  5.44k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|  5.44k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5110|  5.44k|  }
 5111|       |
 5112|  5.44k|  if (ifp->driver->init && !ifp->driver->init(ifp)) {
  ------------------
  |  Branch (5112:7): [True: 5.44k, False: 0]
  |  Branch (5112:28): [True: 0, False: 5.44k]
  ------------------
 5113|      0|    MG_ERROR(("driver init failed"));
  ------------------
  |  | 1014|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5114|  5.44k|  } else {
 5115|  5.44k|    size_t framesize = 1540;
 5116|  5.44k|    ifp->tx.buf = (char *) calloc(1, framesize), ifp->tx.len = framesize;
 5117|  5.44k|    if (ifp->recv_queue.size == 0)
  ------------------
  |  Branch (5117:9): [True: 5.44k, False: 0]
  ------------------
 5118|  5.44k|      ifp->recv_queue.size = ifp->driver->rx ? framesize : 8192;
  ------------------
  |  Branch (5118:30): [True: 5.44k, False: 0]
  ------------------
 5119|  5.44k|    ifp->recv_queue.buf = (char *) calloc(1, ifp->recv_queue.size);
 5120|  5.44k|    ifp->timer_1000ms = mg_millis();
 5121|  5.44k|    mgr->ifp = ifp;
 5122|  5.44k|    ifp->mgr = mgr;
 5123|  5.44k|    ifp->mtu = MG_TCPIP_MTU_DEFAULT;
  ------------------
  |  | 2780|  5.44k|#define MG_TCPIP_MTU_DEFAULT 1500
  ------------------
 5124|  5.44k|    mgr->extraconnsize = sizeof(struct connstate);
 5125|  5.44k|    if (ifp->ip == 0) ifp->enable_dhcp_client = true;
  ------------------
  |  Branch (5125:9): [True: 0, False: 5.44k]
  ------------------
 5126|  5.44k|    memset(ifp->gwmac, 255, sizeof(ifp->gwmac));  // Set best-effort to bcast
 5127|  5.44k|    mg_random(&ifp->eport, sizeof(ifp->eport));   // Random from 0 to 65535
 5128|  5.44k|    ifp->eport |= MG_EPHEMERAL_PORT_BASE;         // Random from
  ------------------
  |  | 4084|  5.44k|#define MG_EPHEMERAL_PORT_BASE 32768
  ------------------
 5129|       |                                           // MG_EPHEMERAL_PORT_BASE to 65535
 5130|  5.44k|    if (ifp->tx.buf == NULL || ifp->recv_queue.buf == NULL) MG_ERROR(("OOM"));
  ------------------
  |  | 1014|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (5130:9): [True: 0, False: 5.44k]
  |  Branch (5130:32): [True: 0, False: 5.44k]
  ------------------
 5131|  5.44k|  }
 5132|  5.44k|}
mg_tcpip_free:
 5134|  5.44k|void mg_tcpip_free(struct mg_tcpip_if *ifp) {
 5135|  5.44k|  free(ifp->recv_queue.buf);
 5136|  5.44k|  free(ifp->tx.buf);
 5137|  5.44k|}
mg_connect_resolved:
 5158|  5.44k|void mg_connect_resolved(struct mg_connection *c) {
 5159|  5.44k|  struct mg_tcpip_if *ifp = c->mgr->ifp;
 5160|  5.44k|  uint32_t rem_ip;
 5161|  5.44k|  memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
 5162|  5.44k|  c->is_resolving = 0;
 5163|  5.44k|  if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE;
  ------------------
  |  | 4084|  5.44k|#define MG_EPHEMERAL_PORT_BASE 32768
  ------------------
                if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE;
  ------------------
  |  | 4084|      0|#define MG_EPHEMERAL_PORT_BASE 32768
  ------------------
  |  Branch (5163:7): [True: 0, False: 5.44k]
  ------------------
 5164|  5.44k|  memcpy(c->loc.ip, &ifp->ip, sizeof(uint32_t));
 5165|  5.44k|  c->loc.port = mg_htons(ifp->eport++);
  ------------------
  |  | 1113|  5.44k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 5166|  5.44k|  MG_DEBUG(("%lu %M -> %M", c->id, mg_print_ip_port, &c->loc, mg_print_ip_port,
  ------------------
  |  | 1016|  5.44k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1009|  5.44k|  do {                      \
  |  |  |  | 1010|  5.44k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|  5.44k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5167|  5.44k|            &c->rem));
 5168|  5.44k|  mg_call(c, MG_EV_RESOLVE, NULL);
 5169|  5.44k|  c->is_connecting = 1;
 5170|  5.44k|  if (c->is_udp && (rem_ip == 0xffffffff || rem_ip == (ifp->ip | ~ifp->mask))) {
  ------------------
  |  Branch (5170:7): [True: 0, False: 5.44k]
  |  Branch (5170:21): [True: 0, False: 0]
  |  Branch (5170:45): [True: 0, False: 0]
  ------------------
 5171|      0|    struct connstate *s = (struct connstate *) (c + 1);
 5172|      0|    memset(s->mac, 0xFF, sizeof(s->mac));  // global or local broadcast
 5173|      0|    mac_resolved(c);
 5174|  5.44k|  } else if (ifp->ip && ((rem_ip & ifp->mask) == (ifp->ip & ifp->mask)) &&
  ------------------
  |  Branch (5174:14): [True: 5.44k, False: 0]
  |  Branch (5174:25): [True: 0, False: 5.44k]
  ------------------
 5175|  5.44k|             rem_ip != ifp->gw) {  // skip if gw (onstatechange -> READY -> ARP)
  ------------------
  |  Branch (5175:14): [True: 0, False: 0]
  ------------------
 5176|       |    // If we're in the same LAN, fire an ARP lookup.
 5177|      0|    MG_DEBUG(("%lu ARP lookup...", c->id));
  ------------------
  |  | 1016|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5178|      0|    mg_tcpip_arp_request(ifp, rem_ip, NULL);
 5179|      0|    settmout(c, MIP_TTYPE_ARP);
  ------------------
  |  | 4106|      0|#define MIP_TTYPE_ARP 2        // ARP resolve sent, waiting for response
  ------------------
 5180|      0|    c->is_arplooking = 1;
 5181|  5.44k|  } else if ((*((uint8_t *) &rem_ip) & 0xE0) == 0xE0) {
  ------------------
  |  Branch (5181:14): [True: 0, False: 5.44k]
  ------------------
 5182|      0|    struct connstate *s = (struct connstate *) (c + 1);  // 224 to 239, E0 to EF
 5183|      0|    uint8_t mcastp[3] = {0x01, 0x00, 0x5E};              // multicast group
 5184|      0|    memcpy(s->mac, mcastp, 3);
 5185|      0|    memcpy(s->mac + 3, ((uint8_t *) &rem_ip) + 1, 3);  // 23 LSb
 5186|      0|    s->mac[3] &= 0x7F;
 5187|      0|    mac_resolved(c);
 5188|  5.44k|  } else {
 5189|  5.44k|    struct connstate *s = (struct connstate *) (c + 1);
 5190|  5.44k|    memcpy(s->mac, ifp->gwmac, sizeof(ifp->gwmac));
 5191|  5.44k|    mac_resolved(c);
 5192|  5.44k|  }
 5193|  5.44k|}
mg_mgr_poll:
 5234|  5.44k|void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
 5235|  5.44k|  struct mg_connection *c, *tmp;
 5236|  5.44k|  uint64_t now = mg_millis();
 5237|  5.44k|  mg_timer_poll(&mgr->timers, now);
 5238|  5.44k|  if (mgr->ifp == NULL || mgr->ifp->driver == NULL) return;
  ------------------
  |  Branch (5238:7): [True: 0, False: 5.44k]
  |  Branch (5238:27): [True: 0, False: 5.44k]
  ------------------
 5239|  5.44k|  mg_tcpip_poll(mgr->ifp, now);
 5240|  10.8k|  for (c = mgr->conns; c != NULL; c = tmp) {
  ------------------
  |  Branch (5240:24): [True: 5.44k, False: 5.44k]
  ------------------
 5241|  5.44k|    tmp = c->next;
 5242|  5.44k|    struct connstate *s = (struct connstate *) (c + 1);
 5243|  5.44k|    mg_call(c, MG_EV_POLL, &now);
 5244|  5.44k|    MG_VERBOSE(("%lu .. %c%c%c%c%c %lu %lu", c->id, c->is_tls ? 'T' : 't',
  ------------------
  |  | 1017|  5.44k|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1009|  5.44k|  do {                      \
  |  |  |  | 1010|  5.44k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  |  Branch (1010:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1010:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1010:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1010:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1010:19): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1011|  5.44k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5245|  5.44k|                c->is_connecting ? 'C' : 'c', c->is_tls_hs ? 'H' : 'h',
 5246|  5.44k|                c->is_resolving ? 'R' : 'r', c->is_closing ? 'C' : 'c',
 5247|  5.44k|                mg_tls_pending(c), c->rtls.len));
 5248|       |    // order is important, TLS conn close with > 1 record in buffer (below)
 5249|  5.44k|    if (c->is_tls && (c->rtls.len > 0 || mg_tls_pending(c) > 0))
  ------------------
  |  Branch (5249:9): [True: 0, False: 5.44k]
  |  Branch (5249:23): [True: 0, False: 0]
  |  Branch (5249:42): [True: 0, False: 0]
  ------------------
 5250|      0|      handle_tls_recv(c);
 5251|  5.44k|    if (can_write(c)) write_conn(c);
  ------------------
  |  Branch (5251:9): [True: 0, False: 5.44k]
  ------------------
 5252|  5.44k|    if (c->is_draining && c->send.len == 0 && s->ttype != MIP_TTYPE_FIN)
  ------------------
  |  | 4108|  1.73k|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
  |  Branch (5252:9): [True: 2.09k, False: 3.34k]
  |  Branch (5252:27): [True: 1.73k, False: 359]
  |  Branch (5252:47): [True: 1.73k, False: 0]
  ------------------
 5253|  1.73k|      init_closure(c);
 5254|       |    // For non-TLS, close immediately upon completing the 3-way closure
 5255|       |    // For TLS, handle any pending data (above) until MIP_TTYPE_FIN expires
 5256|  5.44k|    if (s->twclosure &&
  ------------------
  |  Branch (5256:9): [True: 0, False: 5.44k]
  ------------------
 5257|  5.44k|        (!c->is_tls || (c->rtls.len == 0 && mg_tls_pending(c) == 0)))
  ------------------
  |  Branch (5257:10): [True: 0, False: 0]
  |  Branch (5257:25): [True: 0, False: 0]
  |  Branch (5257:45): [True: 0, False: 0]
  ------------------
 5258|      0|      c->is_closing = 1;
 5259|  5.44k|    if (c->is_closing) close_conn(c);
  ------------------
  |  Branch (5259:9): [True: 5.44k, False: 0]
  ------------------
 5260|  5.44k|  }
 5261|  5.44k|  (void) ms;
 5262|  5.44k|}
mg_pfn_iobuf:
 6939|   810M|void mg_pfn_iobuf(char ch, void *param) {
 6940|   810M|  mg_pfn_iobuf_private(ch, param, true);
 6941|   810M|}
mg_vsnprintf:
 6943|  11.2M|size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap) {
 6944|  11.2M|  struct mg_iobuf io = {(uint8_t *) buf, len, 0, 0};
 6945|  11.2M|  size_t n = mg_vxprintf(mg_putchar_iobuf_static, &io, fmt, ap);
 6946|  11.2M|  if (n < len) buf[n] = '\0';
  ------------------
  |  Branch (6946:7): [True: 11.2M, False: 3.75k]
  ------------------
 6947|  11.2M|  return n;
 6948|  11.2M|}
mg_snprintf:
 6950|  11.2M|size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...) {
 6951|  11.2M|  va_list ap;
 6952|  11.2M|  size_t n;
 6953|  11.2M|  va_start(ap, fmt);
 6954|  11.2M|  n = mg_vsnprintf(buf, len, fmt, &ap);
 6955|  11.2M|  va_end(ap);
 6956|  11.2M|  return n;
 6957|  11.2M|}
mg_vmprintf:
 6959|  2.88k|char *mg_vmprintf(const char *fmt, va_list *ap) {
 6960|  2.88k|  struct mg_iobuf io = {0, 0, 0, 256};
 6961|  2.88k|  mg_vxprintf(mg_pfn_iobuf, &io, fmt, ap);
 6962|  2.88k|  return (char *) io.buf;
 6963|  2.88k|}
mg_mprintf:
 6965|  2.88k|char *mg_mprintf(const char *fmt, ...) {
 6966|  2.88k|  char *s;
 6967|  2.88k|  va_list ap;
 6968|  2.88k|  va_start(ap, fmt);
 6969|  2.88k|  s = mg_vmprintf(fmt, &ap);
 6970|  2.88k|  va_end(ap);
 6971|  2.88k|  return s;
 6972|  2.88k|}
mg_pfn_stdout:
 6974|   155k|void mg_pfn_stdout(char c, void *param) {
 6975|   155k|  putchar(c);
 6976|   155k|  (void) param;
 6977|   155k|}
mg_sntp_parse:
 7857|  10.8k|int64_t mg_sntp_parse(const unsigned char *buf, size_t len) {
 7858|  10.8k|  int64_t epoch_milliseconds = -1;
 7859|  10.8k|  int mode = len > 0 ? buf[0] & 7 : 0;
  ------------------
  |  Branch (7859:14): [True: 5.44k, False: 5.44k]
  ------------------
 7860|  10.8k|  int version = len > 0 ? (buf[0] >> 3) & 7 : 0;
  ------------------
  |  Branch (7860:17): [True: 5.44k, False: 5.44k]
  ------------------
 7861|  10.8k|  if (len < 48) {
  ------------------
  |  Branch (7861:7): [True: 8.66k, False: 2.21k]
  ------------------
 7862|  8.66k|    MG_ERROR(("%s", "corrupt packet"));
  ------------------
  |  | 1014|  8.66k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|  8.66k|  do {                      \
  |  |  |  | 1010|  8.66k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|  8.66k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 7863|  8.66k|  } else if (mode != 4 && mode != 5) {
  ------------------
  |  Branch (7863:14): [True: 1.96k, False: 252]
  |  Branch (7863:27): [True: 1.61k, False: 344]
  ------------------
 7864|  1.61k|    MG_ERROR(("%s", "not a server reply"));
  ------------------
  |  | 1014|  1.61k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|  1.61k|  do {                      \
  |  |  |  | 1010|  1.61k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|  1.61k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 7865|  1.61k|  } else if (buf[1] == 0) {
  ------------------
  |  Branch (7865:14): [True: 4, False: 592]
  ------------------
 7866|      4|    MG_ERROR(("%s", "server sent a kiss of death"));
  ------------------
  |  | 1014|      4|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|      4|  do {                      \
  |  |  |  | 1010|      4|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      4|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 7867|    592|  } else if (version == 4 || version == 3) {
  ------------------
  |  Branch (7867:14): [True: 133, False: 459]
  |  Branch (7867:30): [True: 78, False: 381]
  ------------------
 7868|       |    // int64_t ref = gettimestamp((uint32_t *) &buf[16]);
 7869|    211|    int64_t origin_time = gettimestamp((uint32_t *) &buf[24]);
 7870|    211|    int64_t receive_time = gettimestamp((uint32_t *) &buf[32]);
 7871|    211|    int64_t transmit_time = gettimestamp((uint32_t *) &buf[40]);
 7872|    211|    int64_t now = (int64_t) mg_millis();
 7873|    211|    int64_t latency = (now - origin_time) - (transmit_time - receive_time);
 7874|    211|    epoch_milliseconds = transmit_time + latency / 2;
 7875|    211|    s_boot_timestamp = (uint64_t) (epoch_milliseconds - now);
 7876|    381|  } else {
 7877|    381|    MG_ERROR(("unexpected version: %d", version));
  ------------------
  |  | 1014|    381|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|    381|  do {                      \
  |  |  |  | 1010|    381|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|    381|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 7878|    381|  }
 7879|  10.8k|  return epoch_milliseconds;
 7880|  10.8k|}
mg_str_s:
 8770|  2.56M|struct mg_str mg_str_s(const char *s) {
 8771|  2.56M|  struct mg_str str = {(char *) s, s == NULL ? 0 : strlen(s)};
  ------------------
  |  Branch (8771:36): [True: 77.0k, False: 2.48M]
  ------------------
 8772|  2.56M|  return str;
 8773|  2.56M|}
mg_str_n:
 8775|  5.05M|struct mg_str mg_str_n(const char *s, size_t n) {
 8776|  5.05M|  struct mg_str str = {(char *) s, n};
 8777|  5.05M|  return str;
 8778|  5.05M|}
mg_strcmp:
 8807|  2.97M|int mg_strcmp(const struct mg_str str1, const struct mg_str str2) {
 8808|  2.97M|  size_t i = 0;
 8809|  3.47M|  while (i < str1.len && i < str2.len) {
  ------------------
  |  Branch (8809:10): [True: 2.97M, False: 497k]
  |  Branch (8809:26): [True: 2.97M, False: 5.69k]
  ------------------
 8810|  2.97M|    int c1 = str1.buf[i];
 8811|  2.97M|    int c2 = str2.buf[i];
 8812|  2.97M|    if (c1 < c2) return -1;
  ------------------
  |  Branch (8812:9): [True: 2.38M, False: 587k]
  ------------------
 8813|   587k|    if (c1 > c2) return 1;
  ------------------
  |  Branch (8813:9): [True: 86.2k, False: 501k]
  ------------------
 8814|   501k|    i++;
 8815|   501k|  }
 8816|   503k|  if (i < str1.len) return 1;
  ------------------
  |  Branch (8816:7): [True: 5.69k, False: 497k]
  ------------------
 8817|   497k|  if (i < str2.len) return -1;
  ------------------
  |  Branch (8817:7): [True: 2.56k, False: 494k]
  ------------------
 8818|   494k|  return 0;
 8819|   497k|}
mg_strcasecmp:
 8821|  1.32M|int mg_strcasecmp(const struct mg_str str1, const struct mg_str str2) {
 8822|  1.32M|  size_t i = 0;
 8823|  1.40M|  while (i < str1.len && i < str2.len) {
  ------------------
  |  Branch (8823:10): [True: 1.39M, False: 12.5k]
  |  Branch (8823:26): [True: 1.38M, False: 1.50k]
  ------------------
 8824|  1.38M|    int c1 = mg_tolc(str1.buf[i]);
 8825|  1.38M|    int c2 = mg_tolc(str2.buf[i]);
 8826|  1.38M|    if (c1 < c2) return -1;
  ------------------
  |  Branch (8826:9): [True: 1.30M, False: 88.9k]
  ------------------
 8827|  88.9k|    if (c1 > c2) return 1;
  ------------------
  |  Branch (8827:9): [True: 10.7k, False: 78.2k]
  ------------------
 8828|  78.2k|    i++;
 8829|  78.2k|  }
 8830|  14.0k|  if (i < str1.len) return 1;
  ------------------
  |  Branch (8830:7): [True: 1.50k, False: 12.5k]
  ------------------
 8831|  12.5k|  if (i < str2.len) return -1;
  ------------------
  |  Branch (8831:7): [True: 2.86k, False: 9.68k]
  ------------------
 8832|  9.68k|  return 0;
 8833|  12.5k|}
mg_match:
 8835|  5.44k|bool mg_match(struct mg_str s, struct mg_str p, struct mg_str *caps) {
 8836|  5.44k|  size_t i = 0, j = 0, ni = 0, nj = 0;
 8837|  5.44k|  if (caps) caps->buf = NULL, caps->len = 0;
  ------------------
  |  Branch (8837:7): [True: 0, False: 5.44k]
  ------------------
 8838|   176M|  while (i < p.len || j < s.len) {
  ------------------
  |  Branch (8838:10): [True: 175M, False: 119k]
  |  Branch (8838:23): [True: 113k, False: 5.44k]
  ------------------
 8839|   176M|    if (i < p.len && j < s.len &&
  ------------------
  |  Branch (8839:9): [True: 175M, False: 113k]
  |  Branch (8839:22): [True: 175M, False: 98]
  ------------------
 8840|   176M|        (p.buf[i] == '?' ||
  ------------------
  |  Branch (8840:10): [True: 121k, False: 175M]
  ------------------
 8841|   175M|         (p.buf[i] != '*' && p.buf[i] != '#' && s.buf[j] == p.buf[i]))) {
  ------------------
  |  Branch (8841:11): [True: 175M, False: 487k]
  |  Branch (8841:30): [True: 175M, False: 137k]
  |  Branch (8841:49): [True: 175M, False: 198k]
  ------------------
 8842|   175M|      if (caps == NULL) {
  ------------------
  |  Branch (8842:11): [True: 175M, False: 0]
  ------------------
 8843|   175M|      } else if (p.buf[i] == '?') {
  ------------------
  |  Branch (8843:18): [True: 0, False: 0]
  ------------------
 8844|      0|        caps->buf = &s.buf[j], caps->len = 1;     // Finalize `?` cap
 8845|      0|        caps++, caps->buf = NULL, caps->len = 0;  // Init next cap
 8846|      0|      } else if (caps->buf != NULL && caps->len == 0) {
  ------------------
  |  Branch (8846:18): [True: 0, False: 0]
  |  Branch (8846:39): [True: 0, False: 0]
  ------------------
 8847|      0|        caps->len = (size_t) (&s.buf[j] - caps->buf);  // Finalize current cap
 8848|      0|        caps++, caps->len = 0, caps->buf = NULL;       // Init next cap
 8849|      0|      }
 8850|   175M|      i++, j++;
 8851|   175M|    } else if (i < p.len && (p.buf[i] == '*' || p.buf[i] == '#')) {
  ------------------
  |  Branch (8851:16): [True: 822k, False: 113k]
  |  Branch (8851:30): [True: 487k, False: 335k]
  |  Branch (8851:49): [True: 137k, False: 198k]
  ------------------
 8852|   624k|      if (caps && !caps->buf) caps->len = 0, caps->buf = &s.buf[j];  // Init cap
  ------------------
  |  Branch (8852:11): [True: 0, False: 624k]
  |  Branch (8852:19): [True: 0, False: 0]
  ------------------
 8853|   624k|      ni = i++, nj = j + 1;
 8854|   624k|    } else if (nj > 0 && nj <= s.len && (p.buf[ni] == '#' || s.buf[j] != '/')) {
  ------------------
  |  Branch (8854:16): [True: 312k, False: 0]
  |  Branch (8854:26): [True: 312k, False: 0]
  |  Branch (8854:42): [True: 68.5k, False: 243k]
  |  Branch (8854:62): [True: 243k, False: 0]
  ------------------
 8855|   312k|      i = ni, j = nj;
 8856|   312k|      if (caps && caps->buf == NULL && caps->len == 0) {
  ------------------
  |  Branch (8856:11): [True: 0, False: 312k]
  |  Branch (8856:19): [True: 0, False: 0]
  |  Branch (8856:40): [True: 0, False: 0]
  ------------------
 8857|      0|        caps--, caps->len = 0;  // Restart previous cap
 8858|      0|      }
 8859|   312k|    } else {
 8860|      0|      return false;
 8861|      0|    }
 8862|   176M|  }
 8863|  5.44k|  if (caps && caps->buf && caps->len == 0) {
  ------------------
  |  Branch (8863:7): [True: 0, False: 5.44k]
  |  Branch (8863:15): [True: 0, False: 0]
  |  Branch (8863:28): [True: 0, False: 0]
  ------------------
 8864|      0|    caps->len = (size_t) (&s.buf[j] - caps->buf);
 8865|      0|  }
 8866|  5.44k|  return true;
 8867|  5.44k|}
mg_span:
 8869|  2.41M|bool mg_span(struct mg_str s, struct mg_str *a, struct mg_str *b, char sep) {
 8870|  2.41M|  if (s.len == 0 || s.buf == NULL) {
  ------------------
  |  Branch (8870:7): [True: 422k, False: 1.99M]
  |  Branch (8870:21): [True: 0, False: 1.99M]
  ------------------
 8871|   422k|    return false;  // Empty string, nothing to span - fail
 8872|  1.99M|  } else {
 8873|  1.99M|    size_t len = 0;
 8874|   490M|    while (len < s.len && s.buf[len] != sep) len++;  // Find separator
  ------------------
  |  Branch (8874:12): [True: 489M, False: 858k]
  |  Branch (8874:27): [True: 488M, False: 1.13M]
  ------------------
 8875|  1.99M|    if (a) *a = mg_str_n(s.buf, len);                // Init a
  ------------------
  |  Branch (8875:9): [True: 1.99M, False: 0]
  ------------------
 8876|  1.99M|    if (b) *b = mg_str_n(s.buf + len, s.len - len);  // Init b
  ------------------
  |  Branch (8876:9): [True: 1.99M, False: 0]
  ------------------
 8877|  1.99M|    if (b && len < s.len) b->buf++, b->len--;        // Skip separator
  ------------------
  |  Branch (8877:9): [True: 1.99M, False: 0]
  |  Branch (8877:14): [True: 1.13M, False: 858k]
  ------------------
 8878|  1.99M|    return true;
 8879|  1.99M|  }
 8880|  2.41M|}
mg_str_to_num:
 8882|  26.4k|bool mg_str_to_num(struct mg_str str, int base, void *val, size_t val_len) {
 8883|  26.4k|  size_t i = 0, ndigits = 0;
 8884|  26.4k|  uint64_t max = val_len == sizeof(uint8_t)    ? 0xFF
  ------------------
  |  Branch (8884:18): [True: 24.2k, False: 2.12k]
  ------------------
 8885|  26.4k|                 : val_len == sizeof(uint16_t) ? 0xFFFF
  ------------------
  |  Branch (8885:20): [True: 0, False: 2.12k]
  ------------------
 8886|  2.12k|                 : val_len == sizeof(uint32_t) ? 0xFFFFFFFF
  ------------------
  |  Branch (8886:20): [True: 2.12k, False: 0]
  ------------------
 8887|  2.12k|                                               : (uint64_t) ~0;
 8888|  26.4k|  uint64_t result = 0;
 8889|  26.4k|  if (max == (uint64_t) ~0 && val_len != sizeof(uint64_t)) return false;
  ------------------
  |  Branch (8889:7): [True: 0, False: 26.4k]
  |  Branch (8889:31): [True: 0, False: 0]
  ------------------
 8890|  26.4k|  if (base == 0 && str.len >= 2) {
  ------------------
  |  Branch (8890:7): [True: 0, False: 26.4k]
  |  Branch (8890:20): [True: 0, False: 0]
  ------------------
 8891|      0|    if (str.buf[i] == '0') {
  ------------------
  |  Branch (8891:9): [True: 0, False: 0]
  ------------------
 8892|      0|      i++;
 8893|      0|      base = str.buf[i] == 'b' ? 2 : str.buf[i] == 'x' ? 16 : 10;
  ------------------
  |  Branch (8893:14): [True: 0, False: 0]
  |  Branch (8893:38): [True: 0, False: 0]
  ------------------
 8894|      0|      if (base != 10) ++i;
  ------------------
  |  Branch (8894:11): [True: 0, False: 0]
  ------------------
 8895|      0|    } else {
 8896|      0|      base = 10;
 8897|      0|    }
 8898|      0|  }
 8899|  26.4k|  switch (base) {
 8900|      0|    case 2:
  ------------------
  |  Branch (8900:5): [True: 0, False: 26.4k]
  ------------------
 8901|      0|      while (i < str.len && (str.buf[i] == '0' || str.buf[i] == '1')) {
  ------------------
  |  Branch (8901:14): [True: 0, False: 0]
  |  Branch (8901:30): [True: 0, False: 0]
  |  Branch (8901:51): [True: 0, False: 0]
  ------------------
 8902|      0|        uint64_t digit = (uint64_t) (str.buf[i] - '0');
 8903|      0|        if (result > max / 2) return false;  // Overflow
  ------------------
  |  Branch (8903:13): [True: 0, False: 0]
  ------------------
 8904|      0|        result *= 2;
 8905|      0|        if (result > max - digit) return false;  // Overflow
  ------------------
  |  Branch (8905:13): [True: 0, False: 0]
  ------------------
 8906|      0|        result += digit;
 8907|      0|        i++, ndigits++;
 8908|      0|      }
 8909|      0|      break;
 8910|      0|    case 10:
  ------------------
  |  Branch (8910:5): [True: 0, False: 26.4k]
  ------------------
 8911|      0|      while (i < str.len && str.buf[i] >= '0' && str.buf[i] <= '9') {
  ------------------
  |  Branch (8911:14): [True: 0, False: 0]
  |  Branch (8911:29): [True: 0, False: 0]
  |  Branch (8911:50): [True: 0, False: 0]
  ------------------
 8912|      0|        uint64_t digit = (uint64_t) (str.buf[i] - '0');
 8913|      0|        if (result > max / 10) return false;  // Overflow
  ------------------
  |  Branch (8913:13): [True: 0, False: 0]
  ------------------
 8914|      0|        result *= 10;
 8915|      0|        if (result > max - digit) return false;  // Overflow
  ------------------
  |  Branch (8915:13): [True: 0, False: 0]
  ------------------
 8916|      0|        result += digit;
 8917|      0|        i++, ndigits++;
 8918|      0|      }
 8919|      0|      break;
 8920|  26.4k|    case 16:
  ------------------
  |  Branch (8920:5): [True: 26.4k, False: 0]
  ------------------
 8921|  77.7k|      while (i < str.len) {
  ------------------
  |  Branch (8921:14): [True: 51.3k, False: 26.4k]
  ------------------
 8922|  51.3k|        char c = str.buf[i];
 8923|  51.3k|        uint64_t digit = (c >= '0' && c <= '9')   ? (uint64_t) (c - '0')
  ------------------
  |  Branch (8923:27): [True: 51.3k, False: 0]
  |  Branch (8923:39): [True: 27.7k, False: 23.6k]
  ------------------
 8924|  51.3k|                         : (c >= 'A' && c <= 'F') ? (uint64_t) (c - '7')
  ------------------
  |  Branch (8924:29): [True: 23.6k, False: 0]
  |  Branch (8924:41): [True: 2.34k, False: 21.3k]
  ------------------
 8925|  23.6k|                         : (c >= 'a' && c <= 'f') ? (uint64_t) (c - 'W')
  ------------------
  |  Branch (8925:29): [True: 21.3k, False: 0]
  |  Branch (8925:41): [True: 21.3k, False: 0]
  ------------------
 8926|  21.3k|                                                  : (uint64_t) ~0;
 8927|  51.3k|        if (digit == (uint64_t) ~0) break;
  ------------------
  |  Branch (8927:13): [True: 0, False: 51.3k]
  ------------------
 8928|  51.3k|        if (result > max / 16) return false;  // Overflow
  ------------------
  |  Branch (8928:13): [True: 0, False: 51.3k]
  ------------------
 8929|  51.3k|        result *= 16;
 8930|  51.3k|        if (result > max - digit) return false;  // Overflow
  ------------------
  |  Branch (8930:13): [True: 0, False: 51.3k]
  ------------------
 8931|  51.3k|        result += digit;
 8932|  51.3k|        i++, ndigits++;
 8933|  51.3k|      }
 8934|  26.4k|      break;
 8935|  26.4k|    default:
  ------------------
  |  Branch (8935:5): [True: 0, False: 26.4k]
  ------------------
 8936|      0|      return false;
 8937|  26.4k|  }
 8938|  26.4k|  if (ndigits == 0) return false;
  ------------------
  |  Branch (8938:7): [True: 0, False: 26.4k]
  ------------------
 8939|  26.4k|  if (i != str.len) return false;
  ------------------
  |  Branch (8939:7): [True: 0, False: 26.4k]
  ------------------
 8940|  26.4k|  if (val_len == 1) {
  ------------------
  |  Branch (8940:7): [True: 24.2k, False: 2.12k]
  ------------------
 8941|  24.2k|    *((uint8_t *) val) = (uint8_t) result;
 8942|  24.2k|  } else if (val_len == 2) {
  ------------------
  |  Branch (8942:14): [True: 0, False: 2.12k]
  ------------------
 8943|      0|    *((uint16_t *) val) = (uint16_t) result;
 8944|  2.12k|  } else if (val_len == 4) {
  ------------------
  |  Branch (8944:14): [True: 2.12k, False: 0]
  ------------------
 8945|  2.12k|    *((uint32_t *) val) = (uint32_t) result;
 8946|  2.12k|  } else {
 8947|      0|    *((uint64_t *) val) = (uint64_t) result;
 8948|      0|  }
 8949|  26.4k|  return true;
 8950|  26.4k|}
mg_timer_expired:
 8973|  5.44k|bool mg_timer_expired(uint64_t *t, uint64_t prd, uint64_t now) {
 8974|  5.44k|  if (now + prd < *t) *t = 0;                    // Time wrapped? Reset timer
  ------------------
  |  Branch (8974:7): [True: 0, False: 5.44k]
  ------------------
 8975|  5.44k|  if (*t == 0) *t = now + prd;                   // Firt poll? Set expiration
  ------------------
  |  Branch (8975:7): [True: 0, False: 5.44k]
  ------------------
 8976|  5.44k|  if (*t > now) return false;                    // Not expired yet, return
  ------------------
  |  Branch (8976:7): [True: 0, False: 5.44k]
  ------------------
 8977|  5.44k|  *t = (now - *t) > prd ? now + prd : *t + prd;  // Next expiration time
  ------------------
  |  Branch (8977:8): [True: 27, False: 5.41k]
  ------------------
 8978|  5.44k|  return true;                                   // Expired, return true
 8979|  5.44k|}
mg_timer_poll:
 8981|  5.44k|void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) {
 8982|  5.44k|  struct mg_timer *t, *tmp;
 8983|  5.44k|  for (t = *head; t != NULL; t = tmp) {
  ------------------
  |  Branch (8983:19): [True: 0, False: 5.44k]
  ------------------
 8984|      0|    bool once = t->expire == 0 && (t->flags & MG_TIMER_RUN_NOW) &&
  ------------------
  |  | 1029|      0|#define MG_TIMER_RUN_NOW 2  // Call immediately when timer is set
  ------------------
  |  Branch (8984:17): [True: 0, False: 0]
  |  Branch (8984:35): [True: 0, False: 0]
  ------------------
 8985|      0|                !(t->flags & MG_TIMER_CALLED);  // Handle MG_TIMER_NOW only once
  ------------------
  |  | 8958|      0|#define MG_TIMER_CALLED 4
  ------------------
  |  Branch (8985:17): [True: 0, False: 0]
  ------------------
 8986|      0|    bool expired = mg_timer_expired(&t->expire, t->period_ms, now_ms);
 8987|      0|    tmp = t->next;
 8988|      0|    if (!once && !expired) continue;
  ------------------
  |  Branch (8988:9): [True: 0, False: 0]
  |  Branch (8988:18): [True: 0, False: 0]
  ------------------
 8989|      0|    if ((t->flags & MG_TIMER_REPEAT) || !(t->flags & MG_TIMER_CALLED)) {
  ------------------
  |  | 1028|      0|#define MG_TIMER_REPEAT 1   // Call function periodically
  ------------------
                  if ((t->flags & MG_TIMER_REPEAT) || !(t->flags & MG_TIMER_CALLED)) {
  ------------------
  |  | 8958|      0|#define MG_TIMER_CALLED 4
  ------------------
  |  Branch (8989:9): [True: 0, False: 0]
  |  Branch (8989:41): [True: 0, False: 0]
  ------------------
 8990|      0|      t->fn(t->arg);
 8991|      0|    }
 8992|      0|    t->flags |= MG_TIMER_CALLED;
  ------------------
  |  | 8958|      0|#define MG_TIMER_CALLED 4
  ------------------
 8993|      0|  }
 8994|  5.44k|}
mg_tls_free:
13229|  5.44k|void mg_tls_free(struct mg_connection *c) {
13230|  5.44k|  (void) c;
13231|  5.44k|}
mg_tls_ctx_init:
13242|  5.44k|void mg_tls_ctx_init(struct mg_mgr *mgr) {
13243|  5.44k|  (void) mgr;
13244|  5.44k|}
mg_tls_ctx_free:
13245|  5.44k|void mg_tls_ctx_free(struct mg_mgr *mgr) {
13246|  5.44k|  (void) mgr;
13247|  5.44k|}
mg_url_host:
18881|  5.44k|struct mg_str mg_url_host(const char *url) {
18882|  5.44k|  struct url u = urlparse(url);
18883|  5.44k|  size_t n = u.port  ? u.port - u.host - 1
  ------------------
  |  Branch (18883:14): [True: 5.44k, False: 0]
  ------------------
18884|  5.44k|             : u.uri ? u.uri - u.host
  ------------------
  |  Branch (18884:16): [True: 0, False: 0]
  ------------------
18885|      0|                     : u.end - u.host;
18886|  5.44k|  struct mg_str s = mg_str_n(url + u.host, n);
18887|  5.44k|  return s;
18888|  5.44k|}
mg_url_port:
18895|  5.44k|unsigned short mg_url_port(const char *url) {
18896|  5.44k|  struct url u = urlparse(url);
18897|  5.44k|  unsigned short port = 0;
18898|  5.44k|  if (strncmp(url, "http:", 5) == 0 || strncmp(url, "ws:", 3) == 0) port = 80;
  ------------------
  |  Branch (18898:7): [True: 5.44k, False: 0]
  |  Branch (18898:40): [True: 0, False: 0]
  ------------------
18899|  5.44k|  if (strncmp(url, "wss:", 4) == 0 || strncmp(url, "https:", 6) == 0)
  ------------------
  |  Branch (18899:7): [True: 0, False: 5.44k]
  |  Branch (18899:39): [True: 0, False: 5.44k]
  ------------------
18900|      0|    port = 443;
18901|  5.44k|  if (strncmp(url, "mqtt:", 5) == 0) port = 1883;
  ------------------
  |  Branch (18901:7): [True: 0, False: 5.44k]
  ------------------
18902|  5.44k|  if (strncmp(url, "mqtts:", 6) == 0) port = 8883;
  ------------------
  |  Branch (18902:7): [True: 0, False: 5.44k]
  ------------------
18903|  5.44k|  if (u.port) port = (unsigned short) atoi(url + u.port);
  ------------------
  |  Branch (18903:7): [True: 5.44k, False: 0]
  ------------------
18904|  5.44k|  return port;
18905|  5.44k|}
mg_bzero:
18935|  77.7k|void mg_bzero(volatile unsigned char *buf, size_t len) {
18936|  77.7k|  if (buf != NULL) {
  ------------------
  |  Branch (18936:7): [True: 53.4k, False: 24.3k]
  ------------------
18937|   261G|    while (len--) *buf++ = 0;
  ------------------
  |  Branch (18937:12): [True: 261G, False: 53.4k]
  ------------------
18938|  53.4k|  }
18939|  77.7k|}
mg_random:
18943|  10.8k|bool mg_random(void *buf, size_t len) {
18944|  10.8k|  bool success = false;
18945|  10.8k|  unsigned char *p = (unsigned char *) buf;
18946|       |#if MG_ARCH == MG_ARCH_ESP32
18947|       |  while (len--) *p++ = (unsigned char) (esp_random() & 255);
18948|       |  success = true;
18949|       |#elif MG_ARCH == MG_ARCH_PICOSDK
18950|       |  while (len--) *p++ = (unsigned char) (get_rand_32() & 255);
18951|       |  success = true;
18952|       |#elif MG_ARCH == MG_ARCH_WIN32
18953|       |#if defined(_MSC_VER) && _MSC_VER < 1700
18954|       |  static bool initialised = false;
18955|       |  static HCRYPTPROV hProv;
18956|       |  // CryptGenRandom() implementation earlier than 2008 is weak, see
18957|       |  // https://en.wikipedia.org/wiki/CryptGenRandom
18958|       |  if (!initialised) {
18959|       |    initialised = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
18960|       |                                      CRYPT_VERIFYCONTEXT);
18961|       |  }
18962|       |  if (initialised) success = CryptGenRandom(hProv, len, p);
18963|       |#else
18964|       |  size_t i;
18965|       |  for (i = 0; i < len; i++) {
18966|       |    unsigned int rand_v;
18967|       |    if (rand_s(&rand_v) == 0) {
18968|       |      p[i] = (unsigned char) (rand_v & 255);
18969|       |    } else {
18970|       |      break;
18971|       |    }
18972|       |  }
18973|       |  success = (i == len);
18974|       |#endif
18975|       |
18976|       |#elif MG_ARCH == MG_ARCH_UNIX
18977|       |  FILE *fp = fopen("/dev/urandom", "rb");
18978|  10.8k|  if (fp != NULL) {
  ------------------
  |  Branch (18978:7): [True: 10.8k, False: 0]
  ------------------
18979|  10.8k|    if (fread(buf, 1, len, fp) == len) success = true;
  ------------------
  |  Branch (18979:9): [True: 10.8k, False: 0]
  ------------------
18980|  10.8k|    fclose(fp);
18981|  10.8k|  }
18982|  10.8k|#endif
18983|       |  // If everything above did not work, fallback to a pseudo random generator
18984|  10.8k|  if (success == false) {
  ------------------
  |  Branch (18984:7): [True: 0, False: 10.8k]
  ------------------
18985|      0|    MG_ERROR(("Weak RNG: using rand()"));
  ------------------
  |  | 1014|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
18986|      0|    while (len--) *p++ = (unsigned char) (rand() & 255);
  ------------------
  |  Branch (18986:12): [True: 0, False: 0]
  ------------------
18987|      0|  }
18988|  10.8k|  return success;
18989|  10.8k|}
mg_ntohl:
19005|  12.1k|uint32_t mg_ntohl(uint32_t net) {
19006|  12.1k|  uint8_t data[4] = {0, 0, 0, 0};
19007|  12.1k|  memcpy(&data, &net, sizeof(data));
19008|  12.1k|  return (((uint32_t) data[3]) << 0) | (((uint32_t) data[2]) << 8) |
19009|  12.1k|         (((uint32_t) data[1]) << 16) | (((uint32_t) data[0]) << 24);
19010|  12.1k|}
mg_ntohs:
19012|  91.8k|uint16_t mg_ntohs(uint16_t net) {
19013|  91.8k|  uint8_t data[2] = {0, 0};
19014|  91.8k|  memcpy(&data, &net, sizeof(data));
19015|  91.8k|  return (uint16_t) ((uint16_t) data[1] | (((uint16_t) data[0]) << 8));
19016|  91.8k|}
mg_crc32:
19018|   156k|uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) {
19019|   156k|  static const uint32_t crclut[16] = {
19020|       |      // table for polynomial 0xEDB88320 (reflected)
19021|   156k|      0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, 0x76DC4190, 0x6B6B51F4,
19022|   156k|      0x4DB26158, 0x5005713C, 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C,
19023|   156k|      0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C};
19024|   156k|  crc = ~crc;
19025|  45.4M|  while (len--) {
  ------------------
  |  Branch (19025:10): [True: 45.2M, False: 156k]
  ------------------
19026|  45.2M|    uint8_t b = *(uint8_t *) buf++;
19027|  45.2M|    crc = crclut[(crc ^ b) & 0x0F] ^ (crc >> 4);
19028|  45.2M|    crc = crclut[(crc ^ (b >> 4)) & 0x0F] ^ (crc >> 4);
19029|  45.2M|  }
19030|   156k|  return ~crc;
19031|   156k|}
mg_path_is_sane:
19069|   333k|bool mg_path_is_sane(const struct mg_str path) {
19070|   333k|  const char *s = path.buf;
19071|   333k|  size_t n = path.len;
19072|   333k|  if (path.buf[0] == '.' && path.buf[1] == '.') return false;  // Starts with ..
  ------------------
  |  Branch (19072:7): [True: 333k, False: 0]
  |  Branch (19072:29): [True: 0, False: 333k]
  ------------------
19073|  2.64M|  for (; s[0] != '\0' && n > 0; s++, n--) {
  ------------------
  |  Branch (19073:10): [True: 2.31M, False: 333k]
  |  Branch (19073:26): [True: 2.31M, False: 0]
  ------------------
19074|  2.31M|    if ((s[0] == '/' || s[0] == '\\') && n >= 2) {   // Subdir?
  ------------------
  |  Branch (19074:10): [True: 1.82M, False: 489k]
  |  Branch (19074:25): [True: 1.39k, False: 488k]
  |  Branch (19074:42): [True: 1.82M, False: 0]
  ------------------
19075|  1.82M|      if (s[1] == '.' && s[2] == '.') return false;  // Starts with ..
  ------------------
  |  Branch (19075:11): [True: 15.1k, False: 1.80M]
  |  Branch (19075:26): [True: 70, False: 15.1k]
  ------------------
19076|  1.82M|    }
19077|  2.31M|  }
19078|   333k|  return true;
19079|   333k|}
mg_millis:
19083|  11.0k|uint64_t mg_millis(void) {
19084|       |#if MG_ARCH == MG_ARCH_WIN32
19085|       |  return GetTickCount();
19086|       |#elif MG_ARCH == MG_ARCH_PICOSDK
19087|       |  return time_us_64() / 1000;
19088|       |#elif MG_ARCH == MG_ARCH_ESP8266 || MG_ARCH == MG_ARCH_ESP32 || \
19089|       |    MG_ARCH == MG_ARCH_FREERTOS
19090|       |  return xTaskGetTickCount() * portTICK_PERIOD_MS;
19091|       |#elif MG_ARCH == MG_ARCH_AZURERTOS
19092|       |  return tx_time_get() * (1000 /* MS per SEC */ / TX_TIMER_TICKS_PER_SECOND);
19093|       |#elif MG_ARCH == MG_ARCH_TIRTOS
19094|       |  return (uint64_t) Clock_getTicks();
19095|       |#elif MG_ARCH == MG_ARCH_ZEPHYR
19096|       |  return (uint64_t) k_uptime_get();
19097|       |#elif MG_ARCH == MG_ARCH_CMSIS_RTOS1
19098|       |  return (uint64_t) rt_time_get();
19099|       |#elif MG_ARCH == MG_ARCH_CMSIS_RTOS2
19100|       |  return (uint64_t) ((osKernelGetTickCount() * 1000) / osKernelGetTickFreq());
19101|       |#elif MG_ARCH == MG_ARCH_RTTHREAD
19102|       |  return (uint64_t) ((rt_tick_get() * 1000) / RT_TICK_PER_SECOND);
19103|       |#elif MG_ARCH == MG_ARCH_UNIX && defined(__APPLE__)
19104|       |  // Apple CLOCK_MONOTONIC_RAW is equivalent to CLOCK_BOOTTIME on linux
19105|       |  // Apple CLOCK_UPTIME_RAW is equivalent to CLOCK_MONOTONIC_RAW on linux
19106|       |  return clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1000000;
19107|       |#elif MG_ARCH == MG_ARCH_UNIX
19108|       |  struct timespec ts = {0, 0};
19109|       |  // See #1615 - prefer monotonic clock
19110|  11.0k|#if defined(CLOCK_MONOTONIC_RAW)
19111|       |  // Raw hardware-based time that is not subject to NTP adjustment
19112|  11.0k|  clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
19113|       |#elif defined(CLOCK_MONOTONIC)
19114|       |  // Affected by the incremental adjustments performed by adjtime and NTP
19115|       |  clock_gettime(CLOCK_MONOTONIC, &ts);
19116|       |#else
19117|       |  // Affected by discontinuous jumps in the system time and by the incremental
19118|       |  // adjustments performed by adjtime and NTP
19119|       |  clock_gettime(CLOCK_REALTIME, &ts);
19120|       |#endif
19121|  11.0k|  return ((uint64_t) ts.tv_sec * 1000 + (uint64_t) ts.tv_nsec / 1000000);
19122|       |#elif defined(ARDUINO)
19123|       |  return (uint64_t) millis();
19124|       |#else
19125|       |  return (uint64_t) (time(NULL) * 1000);
19126|       |#endif
19127|  11.0k|}
fuzz.c:_ZL23mg_base64_encode_singlei:
   27|   233M|static int mg_base64_encode_single(int c) {
   28|   233M|  if (c < 26) {
  ------------------
  |  Branch (28:7): [True: 132M, False: 101M]
  ------------------
   29|   132M|    return c + 'A';
   30|   132M|  } else if (c < 52) {
  ------------------
  |  Branch (30:14): [True: 78.4M, False: 22.9M]
  ------------------
   31|  78.4M|    return c - 26 + 'a';
   32|  78.4M|  } else if (c < 62) {
  ------------------
  |  Branch (32:14): [True: 19.3M, False: 3.60M]
  ------------------
   33|  19.3M|    return c - 52 + '0';
   34|  19.3M|  } else {
   35|  3.60M|    return c == 62 ? '+' : '/';
  ------------------
  |  Branch (35:12): [True: 600k, False: 2.99M]
  ------------------
   36|  3.60M|  }
   37|   233M|}
fuzz.c:_ZL23mg_base64_decode_singlei:
   39|  7.67M|static int mg_base64_decode_single(int c) {
   40|  7.67M|  if (c >= 'A' && c <= 'Z') {
  ------------------
  |  Branch (40:7): [True: 179k, False: 7.49M]
  |  Branch (40:19): [True: 5.56k, False: 174k]
  ------------------
   41|  5.56k|    return c - 'A';
   42|  7.67M|  } else if (c >= 'a' && c <= 'z') {
  ------------------
  |  Branch (42:14): [True: 172k, False: 7.50M]
  |  Branch (42:26): [True: 172k, False: 505]
  ------------------
   43|   172k|    return c + 26 - 'a';
   44|  7.50M|  } else if (c >= '0' && c <= '9') {
  ------------------
  |  Branch (44:14): [True: 7.48M, False: 14.8k]
  |  Branch (44:26): [True: 7.48M, False: 3.33k]
  ------------------
   45|  7.48M|    return c + 52 - '0';
   46|  7.48M|  } else if (c == '+') {
  ------------------
  |  Branch (46:14): [True: 1.28k, False: 16.8k]
  ------------------
   47|  1.28k|    return 62;
   48|  16.8k|  } else if (c == '/') {
  ------------------
  |  Branch (48:14): [True: 3.07k, False: 13.7k]
  ------------------
   49|  3.07k|    return 63;
   50|  13.7k|  } else if (c == '=') {
  ------------------
  |  Branch (50:14): [True: 923, False: 12.8k]
  ------------------
   51|    923|    return 64;
   52|  12.8k|  } else {
   53|  12.8k|    return -1;
   54|  12.8k|  }
   55|  7.67M|}
fuzz.c:_ZL17mg_dns_parse_namePKhmmPcm:
  192|    985|                                char *dst, size_t dstlen) {
  193|    985|  return mg_dns_parse_name_depth(s, n, ofs, dst, dstlen, 0, 0);
  194|    985|}
fuzz.c:_ZL23mg_dns_parse_name_depthPKhmmPcmmi:
  156|  1.62k|                                      int depth) {
  157|  1.62k|  size_t i = 0;
  158|  1.62k|  if (tolen > 0 && depth == 0) to[0] = '\0';
  ------------------
  |  Branch (158:7): [True: 511, False: 1.11k]
  |  Branch (158:20): [True: 283, False: 228]
  ------------------
  159|  1.62k|  if (depth > 5) return 0;
  ------------------
  |  Branch (159:7): [True: 14, False: 1.61k]
  ------------------
  160|       |  // MG_INFO(("ofs %lx %x %x", (unsigned long) ofs, s[ofs], s[ofs + 1]));
  161|  4.56k|  while (ofs + i + 1 < len) {
  ------------------
  |  Branch (161:10): [True: 4.50k, False: 66]
  ------------------
  162|  4.50k|    size_t n = s[ofs + i];
  163|  4.50k|    if (n == 0) {
  ------------------
  |  Branch (163:9): [True: 511, False: 3.99k]
  ------------------
  164|    511|      i++;
  165|    511|      break;
  166|    511|    }
  167|  3.99k|    if (n & 0xc0) {
  ------------------
  |  Branch (167:9): [True: 978, False: 3.01k]
  ------------------
  168|    978|      size_t ptr = (((n & 0x3f) << 8) | s[ofs + i + 1]);  // 12 is hdr len
  169|       |      // MG_INFO(("PTR %lx", (unsigned long) ptr));
  170|    978|      if (ptr + 1 < len && (s[ptr] & 0xc0) == 0 &&
  ------------------
  |  Branch (170:11): [True: 703, False: 275]
  |  Branch (170:28): [True: 642, False: 61]
  ------------------
  171|    978|          mg_dns_parse_name_depth(s, len, ptr, to, tolen, j, depth + 1) == 0)
  ------------------
  |  Branch (171:11): [True: 106, False: 536]
  ------------------
  172|    106|        return 0;
  173|    872|      i += 2;
  174|    872|      break;
  175|    978|    }
  176|  3.01k|    if (ofs + i + n + 1 >= len) return 0;
  ------------------
  |  Branch (176:9): [True: 58, False: 2.95k]
  ------------------
  177|  2.95k|    if (j > 0) {
  ------------------
  |  Branch (177:9): [True: 2.65k, False: 297]
  ------------------
  178|  2.65k|      if (j < tolen) to[j] = '.';
  ------------------
  |  Branch (178:11): [True: 635, False: 2.02k]
  ------------------
  179|  2.65k|      j++;
  180|  2.65k|    }
  181|  2.95k|    if (j + n < tolen) memcpy(&to[j], &s[ofs + i + 1], n);
  ------------------
  |  Branch (181:9): [True: 734, False: 2.22k]
  ------------------
  182|  2.95k|    j += n;
  183|  2.95k|    i += n + 1;
  184|  2.95k|    if (j < tolen) to[j] = '\0';  // Zero-terminate this chunk
  ------------------
  |  Branch (184:9): [True: 734, False: 2.22k]
  ------------------
  185|       |    // MG_INFO(("--> [%s]", to));
  186|  2.95k|  }
  187|  1.44k|  if (tolen > 0) to[tolen - 1] = '\0';  // Make sure make sure it is nul-term
  ------------------
  |  Branch (187:7): [True: 511, False: 938]
  ------------------
  188|  1.44k|  return i;
  189|  1.61k|}
fuzz.c:_ZL8is_digiti:
  507|  45.4M|static bool is_digit(int c) {
  508|  45.4M|  return c >= '0' && c <= '9';
  ------------------
  |  Branch (508:10): [True: 41.3M, False: 4.12M]
  |  Branch (508:22): [True: 154k, False: 41.1M]
  ------------------
  509|  45.4M|}
fuzz.c:_ZL6mg_lldPclbb:
  611|  10.7M|static size_t mg_lld(char *buf, int64_t val, bool is_signed, bool is_hex) {
  612|  10.7M|  const char *letters = "0123456789abcdef";
  613|  10.7M|  uint64_t v = (uint64_t) val;
  614|  10.7M|  size_t s = 0, n, i;
  615|  10.7M|  if (is_signed && val < 0) buf[s++] = '-', v = (uint64_t) (-val);
  ------------------
  |  Branch (615:7): [True: 3.85M, False: 6.88M]
  |  Branch (615:20): [True: 2.77M, False: 1.08M]
  ------------------
  616|       |  // This loop prints a number in reverse order. I guess this is because we
  617|       |  // write numbers from right to left: least significant digit comes last.
  618|       |  // Maybe because we use Arabic numbers, and Arabs write RTL?
  619|  10.7M|  if (is_hex) {
  ------------------
  |  Branch (619:7): [True: 0, False: 10.7M]
  ------------------
  620|      0|    for (n = 0; v; v >>= 4) buf[s + n++] = letters[v & 15];
  ------------------
  |  Branch (620:17): [True: 0, False: 0]
  ------------------
  621|  10.7M|  } else {
  622|  87.5M|    for (n = 0; v; v /= 10) buf[s + n++] = letters[v % 10];
  ------------------
  |  Branch (622:17): [True: 76.7M, False: 10.7M]
  ------------------
  623|  10.7M|  }
  624|       |  // Reverse a string
  625|  47.2M|  for (i = 0; i < n / 2; i++) {
  ------------------
  |  Branch (625:15): [True: 36.4M, False: 10.7M]
  ------------------
  626|  36.4M|    char t = buf[s + i];
  627|  36.4M|    buf[s + i] = buf[s + n - i - 1], buf[s + n - i - 1] = t;
  628|  36.4M|  }
  629|  10.7M|  if (val == 0) buf[n++] = '0';  // Handle special case
  ------------------
  |  Branch (629:7): [True: 0, False: 10.7M]
  ------------------
  630|  10.7M|  return n + s;
  631|  10.7M|}
fuzz.c:_ZL4scpyPFvcPvES_Pcm:
  634|  53.3M|                          size_t len) {
  635|  53.3M|  size_t i = 0;
  636|   602M|  while (i < len && buf[i] != '\0') out(buf[i++], ptr);
  ------------------
  |  Branch (636:10): [True: 549M, False: 53.3M]
  |  Branch (636:21): [True: 549M, False: 38]
  ------------------
  637|  53.3M|  return i;
  638|  53.3M|}
fuzz.c:_ZL6p_statPKcPmPl:
 1106|  4.12M|static int p_stat(const char *path, size_t *size, time_t *mtime) {
 1107|       |#if !defined(S_ISDIR)
 1108|       |  MG_ERROR(("stat() API is not supported. %p %p %p", path, size, mtime));
 1109|       |  return 0;
 1110|       |#else
 1111|       |#if MG_ARCH == MG_ARCH_WIN32
 1112|       |  struct _stati64 st;
 1113|       |  wchar_t tmp[MG_PATH_MAX];
 1114|       |  MultiByteToWideChar(CP_UTF8, 0, path, -1, tmp, sizeof(tmp) / sizeof(tmp[0]));
 1115|       |  if (_wstati64(tmp, &st) != 0) return 0;
 1116|       |  // If path is a symlink, windows reports 0 in st.st_size.
 1117|       |  // Get a real file size by opening it and jumping to the end
 1118|       |  if (st.st_size == 0 && (st.st_mode & _S_IFREG)) {
 1119|       |    FILE *fp = _wfopen(tmp, L"rb");
 1120|       |    if (fp != NULL) {
 1121|       |      fseek(fp, 0, SEEK_END);
 1122|       |      if (ftell(fp) > 0) st.st_size = ftell(fp);  // Use _ftelli64 on win10+
 1123|       |      fclose(fp);
 1124|       |    }
 1125|       |  }
 1126|       |#else
 1127|  4.12M|  struct MG_STAT_STRUCT st;
 1128|  4.12M|  if (MG_STAT_FUNC(path, &st) != 0) return 0;
  ------------------
  |  | 1103|  4.12M|#define MG_STAT_FUNC stat
  ------------------
  |  Branch (1128:7): [True: 834k, False: 3.29M]
  ------------------
 1129|  3.29M|#endif
 1130|  3.29M|  if (size) *size = (size_t) st.st_size;
  ------------------
  |  Branch (1130:7): [True: 3.27M, False: 12.2k]
  ------------------
 1131|  3.29M|  if (mtime) *mtime = st.st_mtime;
  ------------------
  |  Branch (1131:7): [True: 3.27M, False: 12.2k]
  ------------------
 1132|  3.29M|  return MG_FS_READ | MG_FS_WRITE | (S_ISDIR(st.st_mode) ? MG_FS_DIR : 0);
 1133|  4.12M|#endif
 1134|  4.12M|}
fuzz.c:_ZL6p_listPKcPFvS0_PvES1_:
 1248|   252k|                   void *userdata) {
 1249|   252k|#if MG_ENABLE_DIRLIST
 1250|   252k|  struct dirent *dp;
 1251|   252k|  DIR *dirp;
 1252|   252k|  if ((dirp = (opendir(dir))) == NULL) return;
  ------------------
  |  Branch (1252:7): [True: 0, False: 252k]
  ------------------
 1253|  4.03M|  while ((dp = readdir(dirp)) != NULL) {
  ------------------
  |  Branch (1253:10): [True: 3.78M, False: 252k]
  ------------------
 1254|  3.78M|    if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue;
  ------------------
  |  Branch (1254:9): [True: 252k, False: 3.53M]
  |  Branch (1254:37): [True: 252k, False: 3.28M]
  ------------------
 1255|  3.28M|    fn(dp->d_name, userdata);
 1256|  3.28M|  }
 1257|   252k|  closedir(dirp);
 1258|       |#else
 1259|       |  (void) dir, (void) fn, (void) userdata;
 1260|       |#endif
 1261|   252k|}
fuzz.c:_ZL6p_openPKci:
 1263|  77.4k|static void *p_open(const char *path, int flags) {
 1264|       |#if MG_ARCH == MG_ARCH_WIN32
 1265|       |  const char *mode = flags == MG_FS_READ ? "rb" : "a+b";
 1266|       |  wchar_t b1[MG_PATH_MAX], b2[10];
 1267|       |  MultiByteToWideChar(CP_UTF8, 0, path, -1, b1, sizeof(b1) / sizeof(b1[0]));
 1268|       |  MultiByteToWideChar(CP_UTF8, 0, mode, -1, b2, sizeof(b2) / sizeof(b2[0]));
 1269|       |  return (void *) _wfopen(b1, b2);
 1270|       |#else
 1271|  77.4k|  const char *mode = flags == MG_FS_READ ? "rbe" : "a+be";  // e for CLOEXEC
  ------------------
  |  Branch (1271:22): [True: 77.4k, False: 0]
  ------------------
 1272|  77.4k|  return (void *) fopen(path, mode);
 1273|  77.4k|#endif
 1274|  77.4k|}
fuzz.c:_ZL11mg_ncasecmpPKcS0_m:
 1373|   468k|static int mg_ncasecmp(const char *s1, const char *s2, size_t len) {
 1374|   468k|  int diff = 0;
 1375|   647k|  if (len > 0) do {
  ------------------
  |  Branch (1375:7): [True: 468k, False: 0]
  ------------------
 1376|   647k|      int c = *s1++, d = *s2++;
 1377|   647k|      if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
  ------------------
  |  Branch (1377:11): [True: 305k, False: 342k]
  |  Branch (1377:23): [True: 158k, False: 147k]
  ------------------
 1378|   647k|      if (d >= 'A' && d <= 'Z') d += 'a' - 'A';
  ------------------
  |  Branch (1378:11): [True: 626k, False: 21.7k]
  |  Branch (1378:23): [True: 453k, False: 173k]
  ------------------
 1379|   647k|      diff = c - d;
 1380|   647k|    } while (diff == 0 && s1[-1] != '\0' && --len > 0);
  ------------------
  |  Branch (1380:14): [True: 197k, False: 450k]
  |  Branch (1380:27): [True: 197k, False: 0]
  |  Branch (1380:45): [True: 179k, False: 17.4k]
  ------------------
 1381|   468k|  return diff;
 1382|   468k|}
fuzz.c:_ZL3isxi:
 1519|  51.9k|static bool isx(int c) {
 1520|  51.9k|  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
  ------------------
  |  Branch (1520:11): [True: 49.9k, False: 1.99k]
  |  Branch (1520:23): [True: 25.7k, False: 24.2k]
  |  Branch (1520:37): [True: 21.9k, False: 4.28k]
  |  Branch (1520:49): [True: 21.2k, False: 715]
  ------------------
 1521|  51.9k|         (c >= 'A' && c <= 'F');
  ------------------
  |  Branch (1521:11): [True: 2.96k, False: 2.04k]
  |  Branch (1521:23): [True: 2.19k, False: 767]
  ------------------
 1522|  51.9k|}
fuzz.c:_ZL4isokh:
 1546|   182M|static bool isok(uint8_t c) {
 1547|   182M|  return c == '\n' || c == '\r' || c == '\t' || c >= ' ';
  ------------------
  |  Branch (1547:10): [True: 802k, False: 181M]
  |  Branch (1547:23): [True: 2.85k, False: 181M]
  |  Branch (1547:36): [True: 42.3k, False: 181M]
  |  Branch (1547:49): [True: 181M, False: 2.42k]
  ------------------
 1548|   182M|}
fuzz.c:_ZL4clenPKcS0_:
 1575|  47.3M|static size_t clen(const char *s, const char *end) {
 1576|  47.3M|  const unsigned char *u = (unsigned char *) s, c = *u;
 1577|  47.3M|  long n = (long) (end - s);
 1578|  47.3M|  if (c > ' ' && c < '~') return 1;  // Usual ascii printed char
  ------------------
  |  Branch (1578:7): [True: 46.6M, False: 676k]
  |  Branch (1578:18): [True: 46.6M, False: 22.0k]
  ------------------
 1579|   698k|  if ((c & 0xe0) == 0xc0 && n > 1 && vcb(u[1])) return 2;  // 2-byte UTF8
  ------------------
  |  Branch (1579:7): [True: 8.60k, False: 690k]
  |  Branch (1579:29): [True: 8.60k, False: 0]
  |  Branch (1579:38): [True: 8.30k, False: 296]
  ------------------
 1580|   690k|  if ((c & 0xf0) == 0xe0 && n > 2 && vcb(u[1]) && vcb(u[2])) return 3;
  ------------------
  |  Branch (1580:7): [True: 4.56k, False: 685k]
  |  Branch (1580:29): [True: 4.56k, False: 0]
  |  Branch (1580:38): [True: 4.39k, False: 170]
  |  Branch (1580:51): [True: 4.30k, False: 98]
  ------------------
 1581|   686k|  if ((c & 0xf8) == 0xf0 && n > 3 && vcb(u[1]) && vcb(u[2]) && vcb(u[3]))
  ------------------
  |  Branch (1581:7): [True: 8.45k, False: 677k]
  |  Branch (1581:29): [True: 8.41k, False: 34]
  |  Branch (1581:38): [True: 7.72k, False: 692]
  |  Branch (1581:51): [True: 7.67k, False: 54]
  |  Branch (1581:64): [True: 7.52k, False: 149]
  ------------------
 1582|  7.52k|    return 4;
 1583|   678k|  return 0;
 1584|   686k|}
fuzz.c:_ZL3vcbh:
 1570|  41.3k|static bool vcb(uint8_t c) {
 1571|  41.3k|  return (c & 0xc0) == 0x80;
 1572|  41.3k|}
fuzz.c:_ZL8skiptornPKcS0_P6mg_str:
 1587|   419k|static const char *skiptorn(const char *s, const char *end, struct mg_str *v) {
 1588|   419k|  v->buf = (char *) s;
 1589|  57.9M|  while (s < end && s[0] != '\n' && s[0] != '\r') s++, v->len++;  // To newline
  ------------------
  |  Branch (1589:10): [True: 57.9M, False: 0]
  |  Branch (1589:21): [True: 57.4M, False: 418k]
  |  Branch (1589:37): [True: 57.4M, False: 1.01k]
  ------------------
 1590|   419k|  if (s >= end || (s[0] == '\r' && s[1] != '\n')) return NULL;    // Stray \r
  ------------------
  |  Branch (1590:7): [True: 0, False: 419k]
  |  Branch (1590:20): [True: 1.01k, False: 418k]
  |  Branch (1590:36): [True: 344, False: 674]
  ------------------
 1591|   418k|  if (s < end && s[0] == '\r') s++;                               // Skip \r
  ------------------
  |  Branch (1591:7): [True: 418k, False: 0]
  |  Branch (1591:18): [True: 674, False: 418k]
  ------------------
 1592|   418k|  if (s >= end || *s++ != '\n') return NULL;                      // Skip \n
  ------------------
  |  Branch (1592:7): [True: 0, False: 418k]
  |  Branch (1592:19): [True: 0, False: 418k]
  ------------------
 1593|   418k|  return s;
 1594|   418k|}
fuzz.c:_ZL21mg_http_parse_headersPKcS0_P14mg_http_headerm:
 1597|   337k|                                  struct mg_http_header *h, size_t max_hdrs) {
 1598|   337k|  size_t i, n;
 1599|   418k|  for (i = 0; i < max_hdrs; i++) {
  ------------------
  |  Branch (1599:15): [True: 417k, False: 330]
  ------------------
 1600|   417k|    struct mg_str k = {NULL, 0}, v = {NULL, 0};
 1601|   417k|    if (s >= end) return false;
  ------------------
  |  Branch (1601:9): [True: 0, False: 417k]
  ------------------
 1602|   417k|    if (s[0] == '\n' || (s[0] == '\r' && s[1] == '\n')) break;
  ------------------
  |  Branch (1602:9): [True: 336k, False: 81.2k]
  |  Branch (1602:26): [True: 615, False: 80.6k]
  |  Branch (1602:42): [True: 599, False: 16]
  ------------------
 1603|  80.6k|    k.buf = (char *) s;
 1604|  15.7M|    while (s < end && s[0] != ':' && (n = clen(s, end)) > 0) s += n, k.len += n;
  ------------------
  |  Branch (1604:12): [True: 15.7M, False: 0]
  |  Branch (1604:23): [True: 15.6M, False: 80.2k]
  |  Branch (1604:38): [True: 15.6M, False: 368]
  ------------------
 1605|  80.6k|    if (k.len == 0) return false;                     // Empty name
  ------------------
  |  Branch (1605:9): [True: 77, False: 80.5k]
  ------------------
 1606|  80.5k|    if (s >= end || clen(s, end) == 0) return false;  // Invalid UTF-8
  ------------------
  |  Branch (1606:9): [True: 0, False: 80.5k]
  |  Branch (1606:21): [True: 298, False: 80.2k]
  ------------------
 1607|  80.2k|    if (*s++ != ':') return false;  // Invalid, not followed by :
  ------------------
  |  Branch (1607:9): [True: 0, False: 80.2k]
  ------------------
 1608|       |    // if (clen(s, end) == 0) return false;        // Invalid UTF-8
 1609|  80.9k|    while (s < end && (s[0] == ' ' || s[0] == '\t')) s++;  // Skip spaces
  ------------------
  |  Branch (1609:12): [True: 80.9k, False: 0]
  |  Branch (1609:24): [True: 376, False: 80.6k]
  |  Branch (1609:39): [True: 335, False: 80.2k]
  ------------------
 1610|  80.2k|    if ((s = skiptorn(s, end, &v)) == NULL) return false;
  ------------------
  |  Branch (1610:9): [True: 17, False: 80.2k]
  ------------------
 1611|  80.8k|    while (v.len > 0 && (v.buf[v.len - 1] == ' ' || v.buf[v.len - 1] == '\t')) {
  ------------------
  |  Branch (1611:12): [True: 65.5k, False: 15.2k]
  |  Branch (1611:26): [True: 296, False: 65.2k]
  |  Branch (1611:53): [True: 274, False: 64.9k]
  ------------------
 1612|    570|      v.len--;  // Trim spaces
 1613|    570|    }
 1614|       |    // MG_INFO(("--HH [%.*s] [%.*s]", (int) k.len, k.buf, (int) v.len, v.buf));
 1615|  80.2k|    h[i].name = k, h[i].value = v;  // Success. Assign values
 1616|  80.2k|  }
 1617|   337k|  return true;
 1618|   337k|}
fuzz.c:_ZL23mg_http_status_code_stri:
 1733|  77.0k|static const char *mg_http_status_code_str(int status_code) {
 1734|  77.0k|  switch (status_code) {
 1735|      0|    case 100: return "Continue";
  ------------------
  |  Branch (1735:5): [True: 0, False: 77.0k]
  ------------------
 1736|      0|    case 101: return "Switching Protocols";
  ------------------
  |  Branch (1736:5): [True: 0, False: 77.0k]
  ------------------
 1737|      0|    case 102: return "Processing";
  ------------------
  |  Branch (1737:5): [True: 0, False: 77.0k]
  ------------------
 1738|      0|    case 200: return "OK";
  ------------------
  |  Branch (1738:5): [True: 0, False: 77.0k]
  ------------------
 1739|      0|    case 201: return "Created";
  ------------------
  |  Branch (1739:5): [True: 0, False: 77.0k]
  ------------------
 1740|      0|    case 202: return "Accepted";
  ------------------
  |  Branch (1740:5): [True: 0, False: 77.0k]
  ------------------
 1741|      0|    case 203: return "Non-authoritative Information";
  ------------------
  |  Branch (1741:5): [True: 0, False: 77.0k]
  ------------------
 1742|      0|    case 204: return "No Content";
  ------------------
  |  Branch (1742:5): [True: 0, False: 77.0k]
  ------------------
 1743|      0|    case 205: return "Reset Content";
  ------------------
  |  Branch (1743:5): [True: 0, False: 77.0k]
  ------------------
 1744|      0|    case 206: return "Partial Content";
  ------------------
  |  Branch (1744:5): [True: 0, False: 77.0k]
  ------------------
 1745|      0|    case 207: return "Multi-Status";
  ------------------
  |  Branch (1745:5): [True: 0, False: 77.0k]
  ------------------
 1746|      0|    case 208: return "Already Reported";
  ------------------
  |  Branch (1746:5): [True: 0, False: 77.0k]
  ------------------
 1747|      0|    case 226: return "IM Used";
  ------------------
  |  Branch (1747:5): [True: 0, False: 77.0k]
  ------------------
 1748|      0|    case 300: return "Multiple Choices";
  ------------------
  |  Branch (1748:5): [True: 0, False: 77.0k]
  ------------------
 1749|      0|    case 301: return "Moved Permanently";
  ------------------
  |  Branch (1749:5): [True: 0, False: 77.0k]
  ------------------
 1750|      0|    case 302: return "Found";
  ------------------
  |  Branch (1750:5): [True: 0, False: 77.0k]
  ------------------
 1751|      0|    case 303: return "See Other";
  ------------------
  |  Branch (1751:5): [True: 0, False: 77.0k]
  ------------------
 1752|      0|    case 304: return "Not Modified";
  ------------------
  |  Branch (1752:5): [True: 0, False: 77.0k]
  ------------------
 1753|      0|    case 305: return "Use Proxy";
  ------------------
  |  Branch (1753:5): [True: 0, False: 77.0k]
  ------------------
 1754|      0|    case 307: return "Temporary Redirect";
  ------------------
  |  Branch (1754:5): [True: 0, False: 77.0k]
  ------------------
 1755|      0|    case 308: return "Permanent Redirect";
  ------------------
  |  Branch (1755:5): [True: 0, False: 77.0k]
  ------------------
 1756|     70|    case 400: return "Bad Request";
  ------------------
  |  Branch (1756:5): [True: 70, False: 77.0k]
  ------------------
 1757|      0|    case 401: return "Unauthorized";
  ------------------
  |  Branch (1757:5): [True: 0, False: 77.0k]
  ------------------
 1758|      0|    case 402: return "Payment Required";
  ------------------
  |  Branch (1758:5): [True: 0, False: 77.0k]
  ------------------
 1759|      0|    case 403: return "Forbidden";
  ------------------
  |  Branch (1759:5): [True: 0, False: 77.0k]
  ------------------
 1760|  77.0k|    case 404: return "Not Found";
  ------------------
  |  Branch (1760:5): [True: 77.0k, False: 70]
  ------------------
 1761|      0|    case 405: return "Method Not Allowed";
  ------------------
  |  Branch (1761:5): [True: 0, False: 77.0k]
  ------------------
 1762|      0|    case 406: return "Not Acceptable";
  ------------------
  |  Branch (1762:5): [True: 0, False: 77.0k]
  ------------------
 1763|      0|    case 407: return "Proxy Authentication Required";
  ------------------
  |  Branch (1763:5): [True: 0, False: 77.0k]
  ------------------
 1764|      0|    case 408: return "Request Timeout";
  ------------------
  |  Branch (1764:5): [True: 0, False: 77.0k]
  ------------------
 1765|      0|    case 409: return "Conflict";
  ------------------
  |  Branch (1765:5): [True: 0, False: 77.0k]
  ------------------
 1766|      0|    case 410: return "Gone";
  ------------------
  |  Branch (1766:5): [True: 0, False: 77.0k]
  ------------------
 1767|      0|    case 411: return "Length Required";
  ------------------
  |  Branch (1767:5): [True: 0, False: 77.0k]
  ------------------
 1768|      0|    case 412: return "Precondition Failed";
  ------------------
  |  Branch (1768:5): [True: 0, False: 77.0k]
  ------------------
 1769|      0|    case 413: return "Payload Too Large";
  ------------------
  |  Branch (1769:5): [True: 0, False: 77.0k]
  ------------------
 1770|      0|    case 414: return "Request-URI Too Long";
  ------------------
  |  Branch (1770:5): [True: 0, False: 77.0k]
  ------------------
 1771|      0|    case 415: return "Unsupported Media Type";
  ------------------
  |  Branch (1771:5): [True: 0, False: 77.0k]
  ------------------
 1772|      0|    case 416: return "Requested Range Not Satisfiable";
  ------------------
  |  Branch (1772:5): [True: 0, False: 77.0k]
  ------------------
 1773|      0|    case 417: return "Expectation Failed";
  ------------------
  |  Branch (1773:5): [True: 0, False: 77.0k]
  ------------------
 1774|      0|    case 418: return "I'm a teapot";
  ------------------
  |  Branch (1774:5): [True: 0, False: 77.0k]
  ------------------
 1775|      0|    case 421: return "Misdirected Request";
  ------------------
  |  Branch (1775:5): [True: 0, False: 77.0k]
  ------------------
 1776|      0|    case 422: return "Unprocessable Entity";
  ------------------
  |  Branch (1776:5): [True: 0, False: 77.0k]
  ------------------
 1777|      0|    case 423: return "Locked";
  ------------------
  |  Branch (1777:5): [True: 0, False: 77.0k]
  ------------------
 1778|      0|    case 424: return "Failed Dependency";
  ------------------
  |  Branch (1778:5): [True: 0, False: 77.0k]
  ------------------
 1779|      0|    case 426: return "Upgrade Required";
  ------------------
  |  Branch (1779:5): [True: 0, False: 77.0k]
  ------------------
 1780|      0|    case 428: return "Precondition Required";
  ------------------
  |  Branch (1780:5): [True: 0, False: 77.0k]
  ------------------
 1781|      0|    case 429: return "Too Many Requests";
  ------------------
  |  Branch (1781:5): [True: 0, False: 77.0k]
  ------------------
 1782|      0|    case 431: return "Request Header Fields Too Large";
  ------------------
  |  Branch (1782:5): [True: 0, False: 77.0k]
  ------------------
 1783|      0|    case 444: return "Connection Closed Without Response";
  ------------------
  |  Branch (1783:5): [True: 0, False: 77.0k]
  ------------------
 1784|      0|    case 451: return "Unavailable For Legal Reasons";
  ------------------
  |  Branch (1784:5): [True: 0, False: 77.0k]
  ------------------
 1785|      0|    case 499: return "Client Closed Request";
  ------------------
  |  Branch (1785:5): [True: 0, False: 77.0k]
  ------------------
 1786|      0|    case 500: return "Internal Server Error";
  ------------------
  |  Branch (1786:5): [True: 0, False: 77.0k]
  ------------------
 1787|      0|    case 501: return "Not Implemented";
  ------------------
  |  Branch (1787:5): [True: 0, False: 77.0k]
  ------------------
 1788|      0|    case 502: return "Bad Gateway";
  ------------------
  |  Branch (1788:5): [True: 0, False: 77.0k]
  ------------------
 1789|      0|    case 503: return "Service Unavailable";
  ------------------
  |  Branch (1789:5): [True: 0, False: 77.0k]
  ------------------
 1790|      0|    case 504: return "Gateway Timeout";
  ------------------
  |  Branch (1790:5): [True: 0, False: 77.0k]
  ------------------
 1791|      0|    case 505: return "HTTP Version Not Supported";
  ------------------
  |  Branch (1791:5): [True: 0, False: 77.0k]
  ------------------
 1792|      0|    case 506: return "Variant Also Negotiates";
  ------------------
  |  Branch (1792:5): [True: 0, False: 77.0k]
  ------------------
 1793|      0|    case 507: return "Insufficient Storage";
  ------------------
  |  Branch (1793:5): [True: 0, False: 77.0k]
  ------------------
 1794|      0|    case 508: return "Loop Detected";
  ------------------
  |  Branch (1794:5): [True: 0, False: 77.0k]
  ------------------
 1795|      0|    case 510: return "Not Extended";
  ------------------
  |  Branch (1795:5): [True: 0, False: 77.0k]
  ------------------
 1796|      0|    case 511: return "Network Authentication Required";
  ------------------
  |  Branch (1796:5): [True: 0, False: 77.0k]
  ------------------
 1797|      0|    case 599: return "Network Connect Timeout Error";
  ------------------
  |  Branch (1797:5): [True: 0, False: 77.0k]
  ------------------
 1798|      0|    default: return "";
  ------------------
  |  Branch (1798:5): [True: 0, False: 77.0k]
  ------------------
 1799|  77.0k|  }
 1800|  77.0k|}
fuzz.c:_ZL18guess_content_type6mg_strPKc:
 1894|  77.0k|static struct mg_str guess_content_type(struct mg_str path, const char *extra) {
 1895|  77.0k|  struct mg_str entry, k, v, s = mg_str(extra), asterisk = mg_str_n("*", 1);
  ------------------
  |  |  913|  77.0k|#define mg_str(s) mg_str_s(s)
  ------------------
 1896|  77.0k|  size_t i = 0;
 1897|       |
 1898|       |  // Shrink path to its extension only
 1899|   291k|  while (i < path.len && path.buf[path.len - i - 1] != '.') i++;
  ------------------
  |  Branch (1899:10): [True: 291k, False: 0]
  |  Branch (1899:26): [True: 214k, False: 77.0k]
  ------------------
 1900|  77.0k|  path.buf += path.len - i;
 1901|  77.0k|  path.len = i;
 1902|       |
 1903|       |  // Process user-provided mime type overrides, if any
 1904|  77.0k|  while (mg_span(s, &entry, &s, ',')) {
  ------------------
  |  Branch (1904:10): [True: 0, False: 77.0k]
  ------------------
 1905|      0|    if (mg_span(entry, &k, &v, '=') &&
  ------------------
  |  Branch (1905:9): [True: 0, False: 0]
  ------------------
 1906|      0|        (mg_strcmp(asterisk, k) == 0 || mg_strcmp(path, k) == 0))
  ------------------
  |  Branch (1906:10): [True: 0, False: 0]
  |  Branch (1906:41): [True: 0, False: 0]
  ------------------
 1907|      0|      return v;
 1908|      0|  }
 1909|       |
 1910|       |  // Process built-in mime types
 1911|  2.38M|  for (i = 0; s_known_types[i].buf != NULL; i += 2) {
  ------------------
  |  Branch (1911:15): [True: 2.30M, False: 76.8k]
  ------------------
 1912|  2.30M|    if (mg_strcmp(path, s_known_types[i]) == 0) return s_known_types[i + 1];
  ------------------
  |  Branch (1912:9): [True: 209, False: 2.30M]
  ------------------
 1913|  2.30M|  }
 1914|       |
 1915|  76.8k|  return mg_str("text/plain; charset=utf-8");
  ------------------
  |  |  913|  76.8k|#define mg_str(s) mg_str_s(s)
  ------------------
 1916|  77.0k|}
fuzz.c:_ZL11uri_to_pathP13mg_connectionP15mg_http_messagePK18mg_http_serve_optsPcm:
 2205|   333k|                       size_t path_size) {
 2206|   333k|  struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
  ------------------
  |  Branch (2206:22): [True: 333k, False: 0]
  ------------------
 2207|   333k|  struct mg_str k, v, part, s = mg_str(opts->root_dir), u = {NULL, 0}, p = u;
  ------------------
  |  |  913|   333k|#define mg_str(s) mg_str_s(s)
  ------------------
 2208|   667k|  while (mg_span(s, &part, &s, ',')) {
  ------------------
  |  Branch (2208:10): [True: 333k, False: 333k]
  ------------------
 2209|   333k|    if (!mg_span(part, &k, &v, '=')) k = part, v = mg_str_n(NULL, 0);
  ------------------
  |  Branch (2209:9): [True: 0, False: 333k]
  ------------------
 2210|   333k|    if (v.len == 0) v = k, k = mg_str("/"), u = k, p = v;
  ------------------
  |  |  913|   333k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (2210:9): [True: 333k, False: 0]
  ------------------
 2211|   333k|    if (hm->uri.len < k.len) continue;
  ------------------
  |  Branch (2211:9): [True: 0, False: 333k]
  ------------------
 2212|   333k|    if (mg_strcmp(k, mg_str_n(hm->uri.buf, k.len)) != 0) continue;
  ------------------
  |  Branch (2212:9): [True: 83.8k, False: 249k]
  ------------------
 2213|   249k|    u = k, p = v;
 2214|   249k|  }
 2215|   333k|  return uri_to_path2(c, hm, fs, u, p, path, path_size);
 2216|   333k|}
fuzz.c:_ZL12uri_to_path2P13mg_connectionP15mg_http_messageP5mg_fs6mg_strS5_Pcm:
 2145|   333k|                        char *path, size_t path_size) {
 2146|   333k|  int flags, tmp;
 2147|       |  // Append URI to the root_dir, and sanitize it
 2148|   333k|  size_t n = mg_snprintf(path, path_size, "%.*s", (int) dir.len, dir.buf);
 2149|   333k|  if (n + 2 >= path_size) {
  ------------------
  |  Branch (2149:7): [True: 0, False: 333k]
  ------------------
 2150|      0|    mg_http_reply(c, 400, "", "Exceeded path size");
 2151|      0|    return -1;
 2152|      0|  }
 2153|   333k|  path[path_size - 1] = '\0';
 2154|       |  // Terminate root dir with slash
 2155|   333k|  if (n > 0 && path[n - 1] != '/') path[n++] = '/', path[n] = '\0';
  ------------------
  |  Branch (2155:7): [True: 333k, False: 0]
  |  Branch (2155:16): [True: 333k, False: 0]
  ------------------
 2156|   333k|  if (url.len < hm->uri.len) {
  ------------------
  |  Branch (2156:7): [True: 84.9k, False: 248k]
  ------------------
 2157|  84.9k|    mg_url_decode(hm->uri.buf + url.len, hm->uri.len - url.len, path + n,
 2158|  84.9k|                  path_size - n, 0);
 2159|  84.9k|  }
 2160|   333k|  path[path_size - 1] = '\0';  // Double-check
 2161|   333k|  if (!mg_path_is_sane(mg_str_n(path, path_size))) {
  ------------------
  |  Branch (2161:7): [True: 70, False: 333k]
  ------------------
 2162|     70|    mg_http_reply(c, 400, "", "Invalid path");
 2163|     70|    return -1;
 2164|     70|  }
 2165|   333k|  n = strlen(path);
 2166|   602k|  while (n > 1 && path[n - 1] == '/') path[--n] = 0;  // Trim trailing slashes
  ------------------
  |  Branch (2166:10): [True: 345k, False: 256k]
  |  Branch (2166:19): [True: 268k, False: 77.3k]
  ------------------
 2167|   333k|  flags = mg_strcmp(hm->uri, mg_str("/")) == 0 ? MG_FS_DIR
  ------------------
  |  |  913|   333k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (2167:11): [True: 244k, False: 89.1k]
  ------------------
 2168|   333k|                                               : fs->st(path, NULL, NULL);
 2169|   333k|  MG_VERBOSE(("%lu %.*s -> %s %d", c->id, (int) hm->uri.len, hm->uri.buf, path,
  ------------------
  |  | 1017|   333k|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1009|   333k|  do {                      \
  |  |  |  | 1010|   333k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|   333k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2170|   333k|              flags));
 2171|   333k|  if (flags == 0) {
  ------------------
  |  Branch (2171:7): [True: 77.0k, False: 256k]
  ------------------
 2172|       |    // Do nothing - let's caller decide
 2173|   256k|  } else if ((flags & MG_FS_DIR) && hm->uri.len > 0 &&
  ------------------
  |  Branch (2173:14): [True: 256k, False: 0]
  |  Branch (2173:37): [True: 256k, False: 0]
  ------------------
 2174|   256k|             hm->uri.buf[hm->uri.len - 1] != '/') {
  ------------------
  |  Branch (2174:14): [True: 4.29k, False: 252k]
  ------------------
 2175|  4.29k|    mg_printf(c,
 2176|  4.29k|              "HTTP/1.1 301 Moved\r\n"
 2177|  4.29k|              "Location: %.*s/\r\n"
 2178|  4.29k|              "Content-Length: 0\r\n"
 2179|  4.29k|              "\r\n",
 2180|  4.29k|              (int) hm->uri.len, hm->uri.buf);
 2181|  4.29k|    c->is_resp = 0;
 2182|  4.29k|    flags = -1;
 2183|   252k|  } else if (flags & MG_FS_DIR) {
  ------------------
  |  Branch (2183:14): [True: 252k, False: 0]
  ------------------
 2184|   252k|    if (((mg_snprintf(path + n, path_size - n, "/" MG_HTTP_INDEX) > 0 &&
  ------------------
  |  |  819|   252k|#define MG_HTTP_INDEX "index.html"
  ------------------
  |  Branch (2184:11): [True: 252k, False: 0]
  ------------------
 2185|   252k|          (tmp = fs->st(path, NULL, NULL)) != 0) ||
  ------------------
  |  Branch (2185:11): [True: 120, False: 252k]
  ------------------
 2186|   252k|         (mg_snprintf(path + n, path_size - n, "/index.shtml") > 0 &&
  ------------------
  |  Branch (2186:11): [True: 252k, False: 0]
  ------------------
 2187|   252k|          (tmp = fs->st(path, NULL, NULL)) != 0))) {
  ------------------
  |  Branch (2187:11): [True: 0, False: 252k]
  ------------------
 2188|    120|      flags = tmp;
 2189|   252k|    } else if ((mg_snprintf(path + n, path_size - n, "/" MG_HTTP_INDEX ".gz") >
  ------------------
  |  Branch (2189:17): [True: 252k, False: 0]
  ------------------
 2190|   252k|                    0 &&
 2191|   252k|                (tmp = fs->st(path, NULL, NULL)) !=
  ------------------
  |  Branch (2191:17): [True: 0, False: 252k]
  ------------------
 2192|   252k|                    0)) {  // check for gzipped index
 2193|      0|      flags = tmp;
 2194|      0|      path[n + 1 + strlen(MG_HTTP_INDEX)] =
  ------------------
  |  |  819|      0|#define MG_HTTP_INDEX "index.html"
  ------------------
 2195|      0|          '\0';  // Remove appended .gz in index file name
 2196|   252k|    } else {
 2197|   252k|      path[n] = '\0';  // Remove appended index file name
 2198|   252k|    }
 2199|   252k|  }
 2200|   333k|  return flags;
 2201|   333k|}
fuzz.c:_ZL7listdirP13mg_connectionP15mg_http_messagePK18mg_http_serve_optsPc:
 2075|   252k|                    const struct mg_http_serve_opts *opts, char *dir) {
 2076|   252k|  const char *sort_js_code =
 2077|   252k|      "<script>function srt(tb, sc, so, d) {"
 2078|   252k|      "var tr = Array.prototype.slice.call(tb.rows, 0),"
 2079|   252k|      "tr = tr.sort(function (a, b) { var c1 = a.cells[sc], c2 = b.cells[sc],"
 2080|   252k|      "n1 = c1.getAttribute('name'), n2 = c2.getAttribute('name'), "
 2081|   252k|      "t1 = a.cells[2].getAttribute('name'), "
 2082|   252k|      "t2 = b.cells[2].getAttribute('name'); "
 2083|   252k|      "return so * (t1 < 0 && t2 >= 0 ? -1 : t2 < 0 && t1 >= 0 ? 1 : "
 2084|   252k|      "n1 ? parseInt(n2) - parseInt(n1) : "
 2085|   252k|      "c1.textContent.trim().localeCompare(c2.textContent.trim())); });";
 2086|   252k|  const char *sort_js_code2 =
 2087|   252k|      "for (var i = 0; i < tr.length; i++) tb.appendChild(tr[i]); "
 2088|   252k|      "if (!d) window.location.hash = ('sc=' + sc + '&so=' + so); "
 2089|   252k|      "};"
 2090|   252k|      "window.onload = function() {"
 2091|   252k|      "var tb = document.getElementById('tb');"
 2092|   252k|      "var m = /sc=([012]).so=(1|-1)/.exec(window.location.hash) || [0, 2, 1];"
 2093|   252k|      "var sc = m[1], so = m[2]; document.onclick = function(ev) { "
 2094|   252k|      "var c = ev.target.rel; if (c) {if (c == sc) so *= -1; srt(tb, c, so); "
 2095|   252k|      "sc = c; ev.preventDefault();}};"
 2096|   252k|      "srt(tb, sc, so, true);"
 2097|   252k|      "}"
 2098|   252k|      "</script>";
 2099|   252k|  struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
  ------------------
  |  Branch (2099:22): [True: 252k, False: 0]
  ------------------
 2100|   252k|  struct printdirentrydata d = {c, hm, opts, dir};
 2101|   252k|  char tmp[10], buf[MG_PATH_MAX];
 2102|   252k|  size_t off, n;
 2103|   252k|  int len = mg_url_decode(hm->uri.buf, hm->uri.len, buf, sizeof(buf), 0);
 2104|   252k|  struct mg_str uri = len > 0 ? mg_str_n(buf, (size_t) len) : hm->uri;
  ------------------
  |  Branch (2104:23): [True: 249k, False: 2.67k]
  ------------------
 2105|       |
 2106|   252k|  mg_printf(c,
 2107|   252k|            "HTTP/1.1 200 OK\r\n"
 2108|   252k|            "Content-Type: text/html; charset=utf-8\r\n"
 2109|   252k|            "%s"
 2110|   252k|            "Content-Length:         \r\n\r\n",
 2111|   252k|            opts->extra_headers == NULL ? "" : opts->extra_headers);
  ------------------
  |  Branch (2111:13): [True: 252k, False: 0]
  ------------------
 2112|   252k|  off = c->send.len;  // Start of body
 2113|   252k|  mg_printf(c,
 2114|   252k|            "<!DOCTYPE html><html><head><title>Index of %.*s</title>%s%s"
 2115|   252k|            "<style>th,td {text-align: left; padding-right: 1em; "
 2116|   252k|            "font-family: monospace; }</style></head>"
 2117|   252k|            "<body><h1>Index of %.*s</h1><table cellpadding=\"0\"><thead>"
 2118|   252k|            "<tr><th><a href=\"#\" rel=\"0\">Name</a></th><th>"
 2119|   252k|            "<a href=\"#\" rel=\"1\">Modified</a></th>"
 2120|   252k|            "<th><a href=\"#\" rel=\"2\">Size</a></th></tr>"
 2121|   252k|            "<tr><td colspan=\"3\"><hr></td></tr>"
 2122|   252k|            "</thead>"
 2123|   252k|            "<tbody id=\"tb\">\n",
 2124|   252k|            (int) uri.len, uri.buf, sort_js_code, sort_js_code2, (int) uri.len,
 2125|   252k|            uri.buf);
 2126|   252k|  mg_printf(c, "%s",
 2127|   252k|            "  <tr><td><a href=\"..\">..</a></td>"
 2128|   252k|            "<td name=-1></td><td name=-1>[DIR]</td></tr>\n");
 2129|       |
 2130|   252k|  fs->ls(dir, printdirentry, &d);
 2131|   252k|  mg_printf(c,
 2132|   252k|            "</tbody><tfoot><tr><td colspan=\"3\"><hr></td></tr></tfoot>"
 2133|   252k|            "</table><address>Mongoose v.%s</address></body></html>\n",
 2134|   252k|            MG_VERSION);
  ------------------
  |  |   23|   252k|#define MG_VERSION "7.17"
  ------------------
 2135|   252k|  n = mg_snprintf(tmp, sizeof(tmp), "%lu", (unsigned long) (c->send.len - off));
 2136|   252k|  if (n > sizeof(tmp)) n = 0;
  ------------------
  |  Branch (2136:7): [True: 0, False: 252k]
  ------------------
 2137|   252k|  memcpy(c->send.buf + off - 12, tmp, n);  // Set content length
 2138|   252k|  c->is_resp = 0;                          // Mark response end
 2139|   252k|}
fuzz.c:_ZL13printdirentryPKcPv:
 2034|  3.28M|static void printdirentry(const char *name, void *userdata) {
 2035|  3.28M|  struct printdirentrydata *d = (struct printdirentrydata *) userdata;
 2036|  3.28M|  struct mg_fs *fs = d->opts->fs == NULL ? &mg_fs_posix : d->opts->fs;
  ------------------
  |  Branch (2036:22): [True: 3.28M, False: 0]
  ------------------
 2037|  3.28M|  size_t size = 0;
 2038|  3.28M|  time_t t = 0;
 2039|  3.28M|  char path[MG_PATH_MAX], sz[40], mod[40];
 2040|  3.28M|  int flags, n = 0;
 2041|       |
 2042|       |  // MG_DEBUG(("[%s] [%s]", d->dir, name));
 2043|  3.28M|  if (mg_snprintf(path, sizeof(path), "%s%c%s", d->dir, '/', name) >
  ------------------
  |  Branch (2043:7): [True: 2.78k, False: 3.27M]
  ------------------
 2044|  3.28M|      sizeof(path)) {
 2045|  2.78k|    MG_ERROR(("%s truncated", name));
  ------------------
  |  | 1014|  2.78k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|  2.78k|  do {                      \
  |  |  |  | 1010|  2.78k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|  2.78k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2046|  3.27M|  } else if ((flags = fs->st(path, &size, &t)) == 0) {
  ------------------
  |  Branch (2046:14): [True: 394, False: 3.27M]
  ------------------
 2047|    394|    MG_ERROR(("%lu stat(%s): %d", d->c->id, path, errno));
  ------------------
  |  | 1014|    394|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|    394|  do {                      \
  |  |  |  | 1010|    394|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|    394|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2048|  3.27M|  } else {
 2049|  3.27M|    const char *slash = flags & MG_FS_DIR ? "/" : "";
  ------------------
  |  Branch (2049:25): [True: 2.77M, False: 504k]
  ------------------
 2050|  3.27M|    if (flags & MG_FS_DIR) {
  ------------------
  |  Branch (2050:9): [True: 2.77M, False: 504k]
  ------------------
 2051|  2.77M|      mg_snprintf(sz, sizeof(sz), "%s", "[DIR]");
 2052|  2.77M|    } else {
 2053|   504k|      mg_snprintf(sz, sizeof(sz), "%lld", (uint64_t) size);
 2054|   504k|    }
 2055|       |#if defined(MG_HTTP_DIRLIST_TIME_FMT)
 2056|       |    {
 2057|       |      char time_str[40];
 2058|       |      struct tm *time_info = localtime(&t);
 2059|       |      strftime(time_str, sizeof time_str, "%Y/%m/%d %H:%M:%S", time_info);
 2060|       |      mg_snprintf(mod, sizeof(mod), "%s", time_str);
 2061|       |    }
 2062|       |#else
 2063|  3.27M|    mg_snprintf(mod, sizeof(mod), "%lu", (unsigned long) t);
 2064|  3.27M|#endif
 2065|  3.27M|    n = (int) mg_url_encode(name, strlen(name), path, sizeof(path));
 2066|  3.27M|    mg_printf(d->c,
 2067|  3.27M|              "  <tr><td><a href=\"%.*s%s\">%s%s</a></td>"
 2068|  3.27M|              "<td name=%lu>%s</td><td name=%lld>%s</td></tr>\n",
 2069|  3.27M|              n, path, slash, name, slash, (unsigned long) t, mod,
 2070|  3.27M|              flags & MG_FS_DIR ? (int64_t) -1 : (int64_t) size, sz);
  ------------------
  |  Branch (2070:15): [True: 2.77M, False: 504k]
  ------------------
 2071|  3.27M|  }
 2072|  3.28M|}
fuzz.c:_ZL14mg_is_url_safei:
 2238|  31.2M|static bool mg_is_url_safe(int c) {
 2239|  31.2M|  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
  ------------------
  |  Branch (2239:11): [True: 31.0M, False: 252k]
  |  Branch (2239:23): [True: 0, False: 31.0M]
  |  Branch (2239:37): [True: 28.9M, False: 2.26M]
  |  Branch (2239:49): [True: 28.9M, False: 0]
  ------------------
 2240|  31.2M|         (c >= 'A' && c <= 'Z') || c == '.' || c == '_' || c == '-' || c == '~';
  ------------------
  |  Branch (2240:11): [True: 2.01M, False: 252k]
  |  Branch (2240:23): [True: 0, False: 2.01M]
  |  Branch (2240:36): [True: 0, False: 2.26M]
  |  Branch (2240:48): [True: 2.01M, False: 252k]
  |  Branch (2240:60): [True: 252k, False: 0]
  |  Branch (2240:72): [True: 0, False: 0]
  ------------------
 2241|  31.2M|}
fuzz.c:_ZL7http_cbP13mg_connectioniPv:
 2374|   690k|static void http_cb(struct mg_connection *c, int ev, void *ev_data) {
 2375|   690k|  if (ev == MG_EV_READ || ev == MG_EV_CLOSE ||
  ------------------
  |  Branch (2375:7): [True: 5.44k, False: 685k]
  |  Branch (2375:27): [True: 5.44k, False: 680k]
  ------------------
 2376|   690k|      (ev == MG_EV_POLL && c->is_accepted && !c->is_draining &&
  ------------------
  |  Branch (2376:8): [True: 5.44k, False: 674k]
  |  Branch (2376:28): [True: 0, False: 5.44k]
  |  Branch (2376:46): [True: 0, False: 0]
  ------------------
 2377|   680k|       c->recv.len > 0)) {  // see #2796
  ------------------
  |  Branch (2377:8): [True: 0, False: 0]
  ------------------
 2378|  10.8k|    struct mg_http_message hm;
 2379|  10.8k|    size_t ofs = 0;  // Parsing offset
 2380|   344k|    while (c->is_resp == 0 && ofs < c->recv.len) {
  ------------------
  |  Branch (2380:12): [True: 344k, False: 0]
  |  Branch (2380:31): [True: 340k, False: 4.39k]
  ------------------
 2381|   340k|      const char *buf = (char *) c->recv.buf + ofs;
 2382|   340k|      int n = mg_http_parse(buf, c->recv.len - ofs, &hm);
 2383|   340k|      struct mg_str *te;  // Transfer - encoding header
 2384|   340k|      bool is_chunked = false;
 2385|   340k|      size_t old_len = c->recv.len;
 2386|   340k|      if (n < 0) {
  ------------------
  |  Branch (2386:11): [True: 2.09k, False: 338k]
  ------------------
 2387|       |        // We don't use mg_error() here, to avoid closing pipelined requests
 2388|       |        // prematurely, see #2592
 2389|  2.09k|        MG_ERROR(("HTTP parse, %lu bytes", c->recv.len));
  ------------------
  |  | 1014|  2.09k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|  2.09k|  do {                      \
  |  |  |  | 1010|  2.09k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|  2.09k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2390|  2.09k|        c->is_draining = 1;
 2391|  2.09k|        mg_hexdump(buf, c->recv.len - ofs > 16 ? 16 : c->recv.len - ofs);
  ------------------
  |  Branch (2391:25): [True: 1.33k, False: 760]
  ------------------
 2392|  2.09k|        c->recv.len = 0;
 2393|  2.09k|        return;
 2394|  2.09k|      }
 2395|   338k|      if (n == 0) break;                 // Request is not buffered yet
  ------------------
  |  Branch (2395:11): [True: 3.30k, False: 334k]
  ------------------
 2396|   334k|      mg_call(c, MG_EV_HTTP_HDRS, &hm);  // Got all HTTP headers
 2397|   334k|      if (c->recv.len != old_len) {
  ------------------
  |  Branch (2397:11): [True: 0, False: 334k]
  ------------------
 2398|       |        // User manipulated received data. Wash our hands
 2399|      0|        MG_DEBUG(("%lu detaching HTTP handler", c->id));
  ------------------
  |  | 1016|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2400|      0|        c->pfn = NULL;
 2401|      0|        return;
 2402|      0|      }
 2403|   334k|      if (ev == MG_EV_CLOSE) {           // If client did not set Content-Length
  ------------------
  |  Branch (2403:11): [True: 903, False: 333k]
  ------------------
 2404|    903|        hm.message.len = c->recv.len - ofs;  // and closes now, deliver MSG
 2405|    903|        hm.body.len = hm.message.len - (size_t) (hm.body.buf - hm.message.buf);
 2406|    903|      }
 2407|   334k|      if ((te = mg_http_get_header(&hm, "Transfer-Encoding")) != NULL) {
  ------------------
  |  Branch (2407:11): [True: 915, False: 333k]
  ------------------
 2408|    915|        if (mg_strcasecmp(*te, mg_str("chunked")) == 0) {
  ------------------
  |  |  913|    915|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (2408:13): [True: 752, False: 163]
  ------------------
 2409|    752|          is_chunked = true;
 2410|    752|        } else {
 2411|    163|          mg_error(c, "Invalid Transfer-Encoding");  // See #2460
 2412|    163|          return;
 2413|    163|        }
 2414|   333k|      } else if (mg_http_get_header(&hm, "Content-length") == NULL) {
  ------------------
  |  Branch (2414:18): [True: 332k, False: 999]
  ------------------
 2415|       |        // #2593: HTTP packets must contain either Transfer-Encoding or
 2416|       |        // Content-length
 2417|   332k|        bool is_response = mg_ncasecmp(hm.method.buf, "HTTP/", 5) == 0;
 2418|   332k|        bool require_content_len = false;
 2419|   332k|        if (!is_response && (mg_strcasecmp(hm.method, mg_str("POST")) == 0 ||
  ------------------
  |  |  913|   325k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (2419:13): [True: 325k, False: 7.57k]
  |  Branch (2419:30): [True: 17, False: 325k]
  ------------------
 2420|   325k|                             mg_strcasecmp(hm.method, mg_str("PUT")) == 0)) {
  ------------------
  |  |  913|   325k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (2420:30): [True: 87, False: 325k]
  ------------------
 2421|       |          // POST and PUT should include an entity body. Therefore, they should
 2422|       |          // contain a Content-length header. Other requests can also contain a
 2423|       |          // body, but their content has no defined semantics (RFC 7231)
 2424|    104|          require_content_len = true;
 2425|    104|          ofs += (size_t) n;  // this request has been processed
 2426|   332k|        } else if (is_response) {
  ------------------
  |  Branch (2426:20): [True: 7.57k, False: 325k]
  ------------------
 2427|       |          // HTTP spec 7.2 Entity body: All other responses must include a body
 2428|       |          // or Content-Length header field defined with a value of 0.
 2429|  7.57k|          int status = mg_http_status(&hm);
 2430|  7.57k|          require_content_len = status >= 200 && status != 204 && status != 304;
  ------------------
  |  Branch (2430:33): [True: 6.96k, False: 612]
  |  Branch (2430:50): [True: 592, False: 6.37k]
  |  Branch (2430:67): [True: 592, False: 0]
  ------------------
 2431|  7.57k|        }
 2432|   332k|        if (require_content_len) {
  ------------------
  |  Branch (2432:13): [True: 696, False: 332k]
  ------------------
 2433|    696|          if (!c->is_client) mg_http_reply(c, 411, "", "");
  ------------------
  |  Branch (2433:15): [True: 0, False: 696]
  ------------------
 2434|    696|          MG_ERROR(("Content length missing from %s", is_response ? "response" : "request"));
  ------------------
  |  | 1014|    696|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|    696|  do {                      \
  |  |  |  | 1010|    696|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  |  Branch (1010:19): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1011|    696|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2435|    696|        }
 2436|   332k|      }
 2437|       |
 2438|   334k|      if (is_chunked) {
  ------------------
  |  Branch (2438:11): [True: 752, False: 333k]
  ------------------
 2439|       |        // For chunked data, strip off prefixes and suffixes from chunks
 2440|       |        // and relocate them right after the headers, then report a message
 2441|    752|        char *s = (char *) c->recv.buf + ofs + n;
 2442|    752|        int o = 0, pl, dl, cl, len = (int) (c->recv.len - ofs - (size_t) n);
 2443|       |
 2444|       |        // Find zero-length chunk (the end of the body)
 2445|  1.79k|        while ((cl = skip_chunk(s + o, len - o, &pl, &dl)) > 0 && dl) o += cl;
  ------------------
  |  Branch (2445:16): [True: 1.34k, False: 443]
  |  Branch (2445:67): [True: 1.04k, False: 309]
  ------------------
 2446|    752|        if (cl == 0) break;  // No zero-len chunk, buffer more data
  ------------------
  |  Branch (2446:13): [True: 161, False: 591]
  ------------------
 2447|    591|        if (cl < 0) {
  ------------------
  |  Branch (2447:13): [True: 282, False: 309]
  ------------------
 2448|    282|          mg_error(c, "Invalid chunk");
 2449|    282|          break;
 2450|    282|        }
 2451|       |
 2452|       |        // Zero chunk found. Second pass: strip + relocate
 2453|    309|        o = 0, hm.body.len = 0, hm.message.len = (size_t) n;
 2454|    545|        while ((cl = skip_chunk(s + o, len - o, &pl, &dl)) > 0) {
  ------------------
  |  Branch (2454:16): [True: 545, False: 0]
  ------------------
 2455|    545|          memmove(s + hm.body.len, s + o + pl, (size_t) dl);
 2456|    545|          o += cl, hm.body.len += (size_t) dl, hm.message.len += (size_t) dl;
 2457|    545|          if (dl == 0) break;
  ------------------
  |  Branch (2457:15): [True: 309, False: 236]
  ------------------
 2458|    545|        }
 2459|    309|        ofs += (size_t) (n + o);
 2460|   333k|      } else {  // Normal, non-chunked data
 2461|   333k|        size_t len = c->recv.len - ofs - (size_t) n;
 2462|   333k|        if (hm.body.len > len) break;  // Buffer more data
  ------------------
  |  Branch (2462:13): [True: 479, False: 333k]
  ------------------
 2463|   333k|        ofs += (size_t) n + hm.body.len;
 2464|   333k|      }
 2465|       |
 2466|   333k|      if (c->is_accepted) c->is_resp = 1;  // Start generating response
  ------------------
  |  Branch (2466:11): [True: 0, False: 333k]
  ------------------
 2467|   333k|      mg_call(c, MG_EV_HTTP_MSG, &hm);     // User handler can clear is_resp
 2468|   333k|      if (c->is_accepted && !c->is_resp) {
  ------------------
  |  Branch (2468:11): [True: 0, False: 333k]
  |  Branch (2468:29): [True: 0, False: 0]
  ------------------
 2469|      0|        struct mg_str *cc = mg_http_get_header(&hm, "Connection");
 2470|      0|        if (cc != NULL && mg_strcasecmp(*cc, mg_str("close")) == 0) {
  ------------------
  |  |  913|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (2470:13): [True: 0, False: 0]
  |  Branch (2470:27): [True: 0, False: 0]
  ------------------
 2471|      0|          c->is_draining = 1;  // honor "Connection: close"
 2472|      0|          break;
 2473|      0|        }
 2474|      0|      }
 2475|   333k|    }
 2476|  8.62k|    if (ofs > 0) mg_iobuf_del(&c->recv, 0, ofs);  // Delete processed data
  ------------------
  |  Branch (2476:9): [True: 1.72k, False: 6.89k]
  ------------------
 2477|  8.62k|  }
 2478|   688k|  (void) ev_data;
 2479|   688k|}
fuzz.c:_ZL10skip_chunkPKciPiS1_:
 2358|  2.33k|static int skip_chunk(const char *buf, int len, int *pl, int *dl) {
 2359|  2.33k|  int i = 0, n = 0;
 2360|  2.33k|  if (len < 3) return 0;
  ------------------
  |  Branch (2360:7): [True: 22, False: 2.31k]
  ------------------
 2361|  1.71M|  while (i < len && is_hex_digit(buf[i])) i++;
  ------------------
  |  Branch (2361:10): [True: 1.71M, False: 59]
  |  Branch (2361:21): [True: 1.70M, False: 2.25k]
  ------------------
 2362|  2.31k|  if (i == 0) return -1;                     // Error, no length specified
  ------------------
  |  Branch (2362:7): [True: 15, False: 2.30k]
  ------------------
 2363|  2.30k|  if (i > (int) sizeof(int) * 2) return -1;  // Chunk length is too big
  ------------------
  |  Branch (2363:7): [True: 94, False: 2.20k]
  ------------------
 2364|  2.20k|  if (len < i + 1 || buf[i] != '\r' || buf[i + 1] != '\n') return -1;  // Error
  ------------------
  |  Branch (2364:7): [True: 18, False: 2.18k]
  |  Branch (2364:22): [True: 33, False: 2.15k]
  |  Branch (2364:40): [True: 28, False: 2.12k]
  ------------------
 2365|  2.12k|  if (mg_str_to_num(mg_str_n(buf, (size_t) i), 16, &n, sizeof(int)) == false)
  ------------------
  |  Branch (2365:7): [True: 0, False: 2.12k]
  ------------------
 2366|      0|    return -1;                    // Decode chunk length, overflow
 2367|  2.12k|  if (n < 0) return -1;           // Error. TODO(): some checks now redundant
  ------------------
  |  Branch (2367:7): [True: 47, False: 2.08k]
  ------------------
 2368|  2.08k|  if (n > len - i - 4) return 0;  // Chunk not yet fully buffered
  ------------------
  |  Branch (2368:7): [True: 139, False: 1.94k]
  ------------------
 2369|  1.94k|  if (buf[i + n + 2] != '\r' || buf[i + n + 3] != '\n') return -1;  // Error
  ------------------
  |  Branch (2369:7): [True: 29, False: 1.91k]
  |  Branch (2369:33): [True: 18, False: 1.89k]
  ------------------
 2370|  1.89k|  *pl = i + 2, *dl = n;
 2371|  1.89k|  return i + 2 + n + 2;
 2372|  1.94k|}
fuzz.c:_ZL12is_hex_digiti:
 2353|  1.71M|static bool is_hex_digit(int c) {
 2354|  1.71M|  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
  ------------------
  |  Branch (2354:11): [True: 1.70M, False: 2.22k]
  |  Branch (2354:23): [True: 525k, False: 1.18M]
  |  Branch (2354:37): [True: 1.18M, False: 4.18k]
  |  Branch (2354:49): [True: 1.18M, False: 21]
  ------------------
 2355|  1.71M|         (c >= 'A' && c <= 'F');
  ------------------
  |  Branch (2355:11): [True: 1.97k, False: 2.23k]
  |  Branch (2355:23): [True: 1.94k, False: 25]
  ------------------
 2356|  1.71M|}
fuzz.c:_ZL7roundupmm:
 2531|  76.0k|static size_t roundup(size_t size, size_t align) {
 2532|  76.0k|  return align == 0 ? size : (size + align - 1) / align * align;
  ------------------
  |  Branch (2532:10): [True: 5.44k, False: 70.5k]
  ------------------
 2533|  76.0k|}
fuzz.c:_ZL7mg_atodPKciPi:
 2627|   395k|static double mg_atod(const char *p, int len, int *numlen) {
 2628|   395k|  double d = 0.0;
 2629|   395k|  int i = 0, sign = 1;
 2630|       |
 2631|       |  // Sign
 2632|   395k|  if (i < len && *p == '-') {
  ------------------
  |  Branch (2632:7): [True: 395k, False: 0]
  |  Branch (2632:18): [True: 184k, False: 210k]
  ------------------
 2633|   184k|    sign = -1, i++;
 2634|   210k|  } else if (i < len && *p == '+') {
  ------------------
  |  Branch (2634:14): [True: 210k, False: 0]
  |  Branch (2634:25): [True: 0, False: 210k]
  ------------------
 2635|      0|    i++;
 2636|      0|  }
 2637|       |
 2638|       |  // Decimal
 2639|  20.4M|  for (; i < len && p[i] >= '0' && p[i] <= '9'; i++) {
  ------------------
  |  Branch (2639:10): [True: 20.4M, False: 150]
  |  Branch (2639:21): [True: 20.1M, False: 327k]
  |  Branch (2639:36): [True: 20.0M, False: 68.6k]
  ------------------
 2640|  20.0M|    d *= 10.0;
 2641|  20.0M|    d += p[i] - '0';
 2642|  20.0M|  }
 2643|   395k|  d *= sign;
 2644|       |
 2645|       |  // Fractional
 2646|   395k|  if (i < len && p[i] == '.') {
  ------------------
  |  Branch (2646:7): [True: 395k, False: 150]
  |  Branch (2646:18): [True: 155k, False: 239k]
  ------------------
 2647|   155k|    double frac = 0.0, base = 0.1;
 2648|   155k|    i++;
 2649|  1.66M|    for (; i < len && p[i] >= '0' && p[i] <= '9'; i++) {
  ------------------
  |  Branch (2649:12): [True: 1.66M, False: 77]
  |  Branch (2649:23): [True: 1.50M, False: 155k]
  |  Branch (2649:38): [True: 1.50M, False: 122]
  ------------------
 2650|  1.50M|      frac += base * (p[i] - '0');
 2651|  1.50M|      base /= 10.0;
 2652|  1.50M|    }
 2653|   155k|    d += frac * sign;
 2654|   155k|  }
 2655|       |
 2656|       |  // Exponential
 2657|   395k|  if (i < len && (p[i] == 'e' || p[i] == 'E')) {
  ------------------
  |  Branch (2657:7): [True: 395k, False: 227]
  |  Branch (2657:19): [True: 5.62k, False: 390k]
  |  Branch (2657:34): [True: 60.6k, False: 329k]
  ------------------
 2658|  66.2k|    int j, exp = 0, minus = 0;
 2659|  66.2k|    i++;
 2660|  66.2k|    if (i < len && p[i] == '-') minus = 1, i++;
  ------------------
  |  Branch (2660:9): [True: 66.1k, False: 39]
  |  Branch (2660:20): [True: 54.3k, False: 11.8k]
  ------------------
 2661|  66.2k|    if (i < len && p[i] == '+') i++;
  ------------------
  |  Branch (2661:9): [True: 66.1k, False: 49]
  |  Branch (2661:20): [True: 1.80k, False: 64.3k]
  ------------------
 2662|  3.20M|    while (i < len && p[i] >= '0' && p[i] <= '9' && exp < 308)
  ------------------
  |  Branch (2662:12): [True: 3.20M, False: 265]
  |  Branch (2662:23): [True: 3.14M, False: 63.2k]
  |  Branch (2662:38): [True: 3.13M, False: 2.73k]
  |  Branch (2662:53): [True: 3.13M, False: 18]
  ------------------
 2663|  3.13M|      exp = exp * 10 + (p[i++] - '0');
 2664|  66.2k|    if (minus) exp = -exp;
  ------------------
  |  Branch (2664:9): [True: 54.3k, False: 11.8k]
  ------------------
 2665|   235k|    for (j = 0; j < exp; j++) d *= 10.0;
  ------------------
  |  Branch (2665:17): [True: 168k, False: 66.2k]
  ------------------
 2666|  2.60M|    for (j = 0; j < -exp; j++) d /= 10.0;
  ------------------
  |  Branch (2666:17): [True: 2.53M, False: 66.2k]
  ------------------
 2667|  66.2k|  }
 2668|       |
 2669|   395k|  if (numlen != NULL) *numlen = i;
  ------------------
  |  Branch (2669:7): [True: 395k, False: 0]
  ------------------
 2670|   395k|  return d;
 2671|   395k|}
fuzz.c:_ZL14mg_pass_stringPKci:
 2613|  30.5k|static int mg_pass_string(const char *s, int len) {
 2614|  30.5k|  int i;
 2615|  38.5M|  for (i = 0; i < len; i++) {
  ------------------
  |  Branch (2615:15): [True: 38.5M, False: 528]
  ------------------
 2616|  38.5M|    if (s[i] == '\\' && i + 1 < len && json_esc(s[i + 1], 1)) {
  ------------------
  |  Branch (2616:9): [True: 3.81M, False: 34.7M]
  |  Branch (2616:25): [True: 3.81M, False: 37]
  |  Branch (2616:40): [True: 3.66M, False: 152k]
  ------------------
 2617|  3.66M|      i++;
 2618|  34.9M|    } else if (s[i] == '\0') {
  ------------------
  |  Branch (2618:16): [True: 84, False: 34.9M]
  ------------------
 2619|     84|      return MG_JSON_INVALID;
 2620|  34.9M|    } else if (s[i] == '"') {
  ------------------
  |  Branch (2620:16): [True: 29.9k, False: 34.8M]
  ------------------
 2621|  29.9k|      return i;
 2622|  29.9k|    }
 2623|  38.5M|  }
 2624|    528|  return MG_JSON_INVALID;
 2625|  30.5k|}
fuzz.c:_ZL8json_escii:
 2605|  3.81M|static char json_esc(int c, int esc) {
 2606|  3.81M|  const char *p, *esc1 = escapeseq(esc), *esc2 = escapeseq(!esc);
 2607|  19.7M|  for (p = esc1; *p != '\0'; p++) {
  ------------------
  |  Branch (2607:18): [True: 19.5M, False: 152k]
  ------------------
 2608|  19.5M|    if (*p == c) return esc2[p - esc1];
  ------------------
  |  Branch (2608:9): [True: 3.66M, False: 15.8M]
  ------------------
 2609|  19.5M|  }
 2610|   152k|  return 0;
 2611|  3.81M|}
fuzz.c:_ZL9escapeseqi:
 2601|  7.62M|static const char *escapeseq(int esc) {
 2602|  7.62M|  return esc ? "\b\f\n\r\t\\\"" : "bfnrt\\\"";
  ------------------
  |  Branch (2602:10): [True: 3.81M, False: 3.81M]
  ------------------
 2603|  7.62M|}
fuzz.c:_ZL4logsPKcm:
 2985|  12.7k|static void logs(const char *buf, size_t len) {
 2986|  12.7k|  size_t i;
 2987|  76.2k|  for (i = 0; i < len; i++) logc(((unsigned char *) buf)[i]);
  ------------------
  |  Branch (2987:15): [True: 63.4k, False: 12.7k]
  ------------------
 2988|  12.7k|}
fuzz.c:_ZL4logch:
 2981|   155k|static void logc(unsigned char c) {
 2982|   155k|  s_log_func((char) c, s_log_func_param);
 2983|   155k|}
fuzz.c:_ZL6nibblej:
 3014|  60.4k|static unsigned char nibble(unsigned c) {
 3015|  60.4k|  return (unsigned char) (c < 10 ? c + '0' : c + 'W');
  ------------------
  |  Branch (3015:27): [True: 46.0k, False: 14.4k]
  ------------------
 3016|  60.4k|}
fuzz.c:_ZL13decode_varintPKhmPm:
 3339|     25|static size_t decode_varint(const uint8_t *buf, size_t len, size_t *value) {
 3340|     25|  size_t multiplier = 1, offset;
 3341|     25|  *value = 0;
 3342|       |
 3343|     65|  for (offset = 0; offset < 4 && offset < len; offset++) {
  ------------------
  |  Branch (3343:20): [True: 59, False: 6]
  |  Branch (3343:34): [True: 55, False: 4]
  ------------------
 3344|     55|    uint8_t encoded_byte = buf[offset];
 3345|     55|    *value += (encoded_byte & 0x7f) * multiplier;
 3346|     55|    multiplier *= 128;
 3347|       |
 3348|     55|    if ((encoded_byte & 0x80) == 0) return offset + 1;
  ------------------
  |  Branch (3348:9): [True: 15, False: 40]
  ------------------
 3349|     55|  }
 3350|       |
 3351|     10|  return 0;
 3352|     25|}
fuzz.c:_ZL8mg_atone6mg_strP7mg_addr:
 3831|  5.44k|static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
 3832|  5.44k|  if (str.len > 0) return false;
  ------------------
  |  Branch (3832:7): [True: 5.44k, False: 0]
  ------------------
 3833|      0|  memset(addr->ip, 0, sizeof(addr->ip));
 3834|      0|  addr->is_ip6 = false;
 3835|      0|  return true;
 3836|  5.44k|}
fuzz.c:_ZL8mg_atonl6mg_strP7mg_addr:
 3823|  5.44k|static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
 3824|  5.44k|  uint32_t localhost = mg_htonl(0x7f000001);
  ------------------
  |  | 1114|  5.44k|#define mg_htonl(x) mg_ntohl(x)
  ------------------
 3825|  5.44k|  if (mg_strcasecmp(str, mg_str("localhost")) != 0) return false;
  ------------------
  |  |  913|  5.44k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (3825:7): [True: 0, False: 5.44k]
  ------------------
 3826|  5.44k|  memcpy(addr->ip, &localhost, sizeof(uint32_t));
 3827|  5.44k|  addr->is_ip6 = false;
 3828|  5.44k|  return true;
 3829|  5.44k|}
fuzz.c:_ZL12ether_outputP11mg_tcpip_ifm:
 4264|  10.9k|static size_t ether_output(struct mg_tcpip_if *ifp, size_t len) {
 4265|  10.9k|  size_t n = ifp->driver->tx(ifp->tx.buf, len, ifp);
 4266|  10.9k|  if (n == len) ifp->nsent++;
  ------------------
  |  Branch (4266:7): [True: 10.9k, False: 0]
  ------------------
 4267|  10.9k|  return n;
 4268|  10.9k|}
fuzz.c:_ZL5tx_ipP11mg_tcpip_ifPhhjjm:
 4304|  5.49k|                        size_t plen) {
 4305|  5.49k|  struct eth *eth = (struct eth *) ifp->tx.buf;
 4306|  5.49k|  struct ip *ip = (struct ip *) (eth + 1);
 4307|  5.49k|  memcpy(eth->dst, mac_dst, sizeof(eth->dst));
 4308|  5.49k|  memcpy(eth->src, ifp->mac, sizeof(eth->src));  // Use our MAC
 4309|  5.49k|  eth->type = mg_htons(0x800);
  ------------------
  |  | 1113|  5.49k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 4310|  5.49k|  memset(ip, 0, sizeof(*ip));
 4311|  5.49k|  ip->ver = 0x45;               // Version 4, header length 5 words
 4312|  5.49k|  ip->frag = mg_htons(0x4000);  // Don't fragment
  ------------------
  |  | 1113|  5.49k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 4313|  5.49k|  ip->len = mg_htons((uint16_t) (sizeof(*ip) + plen));
  ------------------
  |  | 1113|  5.49k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 4314|  5.49k|  ip->ttl = 64;
 4315|  5.49k|  ip->proto = proto;
 4316|  5.49k|  ip->src = ip_src;
 4317|  5.49k|  ip->dst = ip_dst;
 4318|  5.49k|  ip->csum = ipcsum(ip, sizeof(*ip));
 4319|  5.49k|  return ip;
 4320|  5.49k|}
fuzz.c:_ZL6ipcsumPKvm:
 4246|  5.53k|static uint16_t ipcsum(const void *buf, size_t len) {
 4247|  5.53k|  uint32_t sum = csumup(0, buf, len);
 4248|  5.53k|  return csumfin(sum);
 4249|  5.53k|}
fuzz.c:_ZL6csumupjPKvm:
 4234|  27.3k|static uint32_t csumup(uint32_t sum, const void *buf, size_t len) {
 4235|  27.3k|  size_t i;
 4236|  27.3k|  const uint8_t *p = (const uint8_t *) buf;
 4237|   332k|  for (i = 0; i < len; i++) sum += i & 1 ? p[i] : ((uint32_t) p[i]) << 8;
  ------------------
  |  Branch (4237:15): [True: 305k, False: 27.3k]
  |  Branch (4237:36): [True: 152k, False: 152k]
  ------------------
 4238|  27.3k|  return sum;
 4239|  27.3k|}
fuzz.c:_ZL7csumfinj:
 4241|  10.9k|static uint16_t csumfin(uint32_t sum) {
 4242|  21.9k|  while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
  ------------------
  |  Branch (4242:10): [True: 10.9k, False: 10.9k]
  ------------------
 4243|  10.9k|  return mg_htons(~sum & 0xffff);
  ------------------
  |  | 1113|  10.9k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 4244|  10.9k|}
fuzz.c:_ZL6tx_tcpP11mg_tcpip_ifPhjhttjjPKvm:
 4602|  5.45k|                     uint32_t seq, uint32_t ack, const void *buf, size_t len) {
 4603|       |#if 0
 4604|       |  uint8_t opts[] = {2, 4, 5, 0xb4, 4, 2, 0, 0};  // MSS = 1460, SACK permitted
 4605|       |  if (flags & TH_SYN) {
 4606|       |    // Handshake? Set MSS
 4607|       |    buf = opts;
 4608|       |    len = sizeof(opts);
 4609|       |  }
 4610|       |#endif
 4611|  5.45k|  struct ip *ip =
 4612|  5.45k|      tx_ip(ifp, dst_mac, 6, ifp->ip, dst_ip, sizeof(struct tcp) + len);
 4613|  5.45k|  struct tcp *tcp = (struct tcp *) (ip + 1);
 4614|  5.45k|  memset(tcp, 0, sizeof(*tcp));
 4615|  5.45k|  if (buf != NULL && len) memmove(tcp + 1, buf, len);
  ------------------
  |  Branch (4615:7): [True: 0, False: 5.45k]
  |  Branch (4615:22): [True: 0, False: 0]
  ------------------
 4616|  5.45k|  tcp->sport = sport;
 4617|  5.45k|  tcp->dport = dport;
 4618|  5.45k|  tcp->seq = seq;
 4619|  5.45k|  tcp->ack = ack;
 4620|  5.45k|  tcp->flags = flags;
 4621|  5.45k|  tcp->win = mg_htons(MIP_TCP_WIN);
  ------------------
  |  | 1113|  5.45k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 4622|  5.45k|  tcp->off = (uint8_t) (sizeof(*tcp) / 4 << 4);
 4623|       |  // if (flags & TH_SYN) tcp->off = 0x70;  // Handshake? header size 28 bytes
 4624|       |
 4625|  5.45k|  uint32_t cs = 0;
 4626|  5.45k|  uint16_t n = (uint16_t) (sizeof(*tcp) + len);
 4627|  5.45k|  uint8_t pseudo[] = {0, ip->proto, (uint8_t) (n >> 8), (uint8_t) (n & 255)};
 4628|  5.45k|  cs = csumup(cs, tcp, n);
 4629|  5.45k|  cs = csumup(cs, &ip->src, sizeof(ip->src));
 4630|  5.45k|  cs = csumup(cs, &ip->dst, sizeof(ip->dst));
 4631|  5.45k|  cs = csumup(cs, pseudo, sizeof(pseudo));
 4632|  5.45k|  tcp->csum = csumfin(cs);
 4633|  5.45k|  MG_VERBOSE(("TCP %M:%hu -> %M:%hu fl %x len %u", mg_print_ip4, &ip->src,
  ------------------
  |  | 1017|  5.45k|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1009|  5.45k|  do {                      \
  |  |  |  | 1010|  5.45k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|  5.45k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4634|  5.45k|              mg_ntohs(tcp->sport), mg_print_ip4, &ip->dst,
 4635|  5.45k|              mg_ntohs(tcp->dport), tcp->flags, len));
 4636|       |  // mg_hexdump(ifp->tx.buf, PDIFF(ifp->tx.buf, tcp + 1) + len);
 4637|  5.45k|  return ether_output(ifp, PDIFF(ifp->tx.buf, tcp + 1) + len);
  ------------------
  |  | 4085|  5.45k|#define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a))))
  ------------------
 4638|  5.45k|}
fuzz.c:_ZL8settmoutP13mg_connectionh:
 4251|  10.8k|static void settmout(struct mg_connection *c, uint8_t type) {
 4252|  10.8k|  struct mg_tcpip_if *ifp = c->mgr->ifp;
 4253|  10.8k|  struct connstate *s = (struct connstate *) (c + 1);
 4254|  10.8k|  unsigned n = type == MIP_TTYPE_ACK   ? MIP_TCP_ACK_MS
  ------------------
  |  | 4105|  10.8k|#define MIP_TTYPE_ACK 1        // Peer sent us data, we have to ack it soon
  ------------------
                unsigned n = type == MIP_TTYPE_ACK   ? MIP_TCP_ACK_MS
  ------------------
  |  | 4091|      0|#define MIP_TCP_ACK_MS 150    // Timeout for ACKing
  ------------------
  |  Branch (4254:16): [True: 0, False: 10.8k]
  ------------------
 4255|  10.8k|               : type == MIP_TTYPE_ARP ? MIP_ARP_RESP_MS
  ------------------
  |  | 4106|  10.8k|#define MIP_TTYPE_ARP 2        // ARP resolve sent, waiting for response
  ------------------
                             : type == MIP_TTYPE_ARP ? MIP_ARP_RESP_MS
  ------------------
  |  | 4092|      0|#define MIP_ARP_RESP_MS 100   // Timeout for ARP response
  ------------------
  |  Branch (4255:18): [True: 0, False: 10.8k]
  ------------------
 4256|  10.8k|               : type == MIP_TTYPE_SYN ? MIP_TCP_SYN_MS
  ------------------
  |  | 4107|  10.8k|#define MIP_TTYPE_SYN 3        // SYN sent, waiting for response
  ------------------
                             : type == MIP_TTYPE_SYN ? MIP_TCP_SYN_MS
  ------------------
  |  | 4093|  5.44k|#define MIP_TCP_SYN_MS 15000  // Timeout for connection establishment
  ------------------
  |  Branch (4256:18): [True: 5.44k, False: 5.44k]
  ------------------
 4257|  10.8k|               : type == MIP_TTYPE_FIN ? MIP_TCP_FIN_MS
  ------------------
  |  | 4108|  5.44k|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
                             : type == MIP_TTYPE_FIN ? MIP_TCP_FIN_MS
  ------------------
  |  | 4094|      0|#define MIP_TCP_FIN_MS 1000   // Timeout for closing connection
  ------------------
  |  Branch (4257:18): [True: 0, False: 5.44k]
  ------------------
 4258|  5.44k|                                       : MIP_TCP_KEEPALIVE_MS;
  ------------------
  |  | 4088|  16.3k|#define MIP_TCP_KEEPALIVE_MS 45000  // TCP keep-alive period, ms
  ------------------
 4259|  10.8k|  s->timer = ifp->now + n;
 4260|  10.8k|  s->ttype = type;
 4261|  10.8k|  MG_VERBOSE(("%lu %d -> %llx", c->id, type, s->timer));
  ------------------
  |  | 1017|  10.8k|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1009|  10.8k|  do {                      \
  |  |  |  | 1010|  10.8k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|  10.8k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4262|  10.8k|}
fuzz.c:_ZL12mac_resolvedP13mg_connection:
 5148|  5.44k|static void mac_resolved(struct mg_connection *c) {
 5149|  5.44k|  if (c->is_udp) {
  ------------------
  |  Branch (5149:7): [True: 0, False: 5.44k]
  ------------------
 5150|      0|    c->is_connecting = 0;
 5151|      0|    mg_call(c, MG_EV_CONNECT, NULL);
 5152|  5.44k|  } else {
 5153|  5.44k|    send_syn(c);
 5154|  5.44k|    settmout(c, MIP_TTYPE_SYN);
  ------------------
  |  | 4107|  5.44k|#define MIP_TTYPE_SYN 3        // SYN sent, waiting for response
  ------------------
 5155|  5.44k|  }
 5156|  5.44k|}
fuzz.c:_ZL8send_synP13mg_connection:
 5139|  5.44k|static void send_syn(struct mg_connection *c) {
 5140|  5.44k|  struct connstate *s = (struct connstate *) (c + 1);
 5141|  5.44k|  uint32_t isn = mg_htonl((uint32_t) mg_ntohs(c->loc.port));
  ------------------
  |  | 1114|  5.44k|#define mg_htonl(x) mg_ntohl(x)
  ------------------
 5142|  5.44k|  uint32_t rem_ip;
 5143|  5.44k|  memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
 5144|  5.44k|  tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_SYN, c->loc.port, c->rem.port, isn, 0,
  ------------------
  |  | 4178|  5.44k|#define TH_SYN 0x02
  ------------------
 5145|  5.44k|         NULL, 0);
 5146|  5.44k|}
fuzz.c:_ZL13mg_tcpip_pollP11mg_tcpip_ifm:
 4979|  5.44k|static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
 4980|  5.44k|  struct mg_connection *c;
 4981|  5.44k|  bool expired_1000ms = mg_timer_expired(&ifp->timer_1000ms, 1000, now);
 4982|  5.44k|  ifp->now = now;
 4983|       |
 4984|  5.44k|  if (expired_1000ms) {
  ------------------
  |  Branch (4984:7): [True: 5.44k, False: 0]
  ------------------
 4985|       |#if MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
 4986|       |    const char *names[] = {"down", "up", "req", "ip", "ready"};
 4987|       |    MG_INFO(("Status: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u",
 4988|       |             names[ifp->state], mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent,
 4989|       |             ifp->ndrop, ifp->nerr));
 4990|       |#endif
 4991|  5.44k|  }
 4992|       |  // Handle gw ARP request timeout, order is important
 4993|  5.44k|  if (expired_1000ms && ifp->state == MG_TCPIP_STATE_IP) {
  ------------------
  |  | 2796|  5.44k|#define MG_TCPIP_STATE_IP 3     // Interface is up and has an IP assigned
  ------------------
  |  Branch (4993:7): [True: 5.44k, False: 0]
  |  Branch (4993:25): [True: 0, False: 5.44k]
  ------------------
 4994|      0|    ifp->state = MG_TCPIP_STATE_READY;  // keep best-effort MAC
  ------------------
  |  | 2797|      0|#define MG_TCPIP_STATE_READY 4  // Interface has fully come up, ready to work
  ------------------
 4995|      0|    onstatechange(ifp);
 4996|      0|  }
 4997|       |  // Handle physical interface up/down status
 4998|  5.44k|  if (expired_1000ms && ifp->driver->up) {
  ------------------
  |  Branch (4998:7): [True: 5.44k, False: 0]
  |  Branch (4998:25): [True: 5.44k, False: 0]
  ------------------
 4999|  5.44k|    bool up = ifp->driver->up(ifp);
 5000|  5.44k|    bool current = ifp->state != MG_TCPIP_STATE_DOWN;
  ------------------
  |  | 2793|  5.44k|#define MG_TCPIP_STATE_DOWN 0   // Interface is down
  ------------------
 5001|  5.44k|    if (!up && ifp->enable_dhcp_client) ifp->ip = 0;
  ------------------
  |  Branch (5001:9): [True: 0, False: 5.44k]
  |  Branch (5001:16): [True: 0, False: 0]
  ------------------
 5002|  5.44k|    if (up != current) {  // link state has changed
  ------------------
  |  Branch (5002:9): [True: 5.44k, False: 0]
  ------------------
 5003|  5.44k|      ifp->state = up == false ? MG_TCPIP_STATE_DOWN
  ------------------
  |  | 2793|      0|#define MG_TCPIP_STATE_DOWN 0   // Interface is down
  ------------------
  |  Branch (5003:20): [True: 0, False: 5.44k]
  ------------------
 5004|  5.44k|                   : ifp->enable_dhcp_client || ifp->ip == 0
  ------------------
  |  Branch (5004:22): [True: 0, False: 5.44k]
  |  Branch (5004:49): [True: 0, False: 5.44k]
  ------------------
 5005|  5.44k|                       ? MG_TCPIP_STATE_UP
  ------------------
  |  | 2794|      0|#define MG_TCPIP_STATE_UP 1     // Interface is up
  ------------------
 5006|  5.44k|                       : MG_TCPIP_STATE_IP;
  ------------------
  |  | 2796|  10.8k|#define MG_TCPIP_STATE_IP 3     // Interface is up and has an IP assigned
  ------------------
 5007|  5.44k|      onstatechange(ifp);
 5008|  5.44k|    } else if (!ifp->enable_dhcp_client && ifp->state == MG_TCPIP_STATE_UP &&
  ------------------
  |  | 2794|      0|#define MG_TCPIP_STATE_UP 1     // Interface is up
  ------------------
  |  Branch (5008:16): [True: 0, False: 0]
  |  Branch (5008:44): [True: 0, False: 0]
  ------------------
 5009|      0|               ifp->ip) {
  ------------------
  |  Branch (5009:16): [True: 0, False: 0]
  ------------------
 5010|      0|      ifp->state = MG_TCPIP_STATE_IP;  // ifp->fn has set an IP
  ------------------
  |  | 2796|      0|#define MG_TCPIP_STATE_IP 3     // Interface is up and has an IP assigned
  ------------------
 5011|      0|      onstatechange(ifp);
 5012|      0|    }
 5013|  5.44k|    if (ifp->state == MG_TCPIP_STATE_DOWN) MG_ERROR(("Network is down"));
  ------------------
  |  | 2793|  5.44k|#define MG_TCPIP_STATE_DOWN 0   // Interface is down
  ------------------
                  if (ifp->state == MG_TCPIP_STATE_DOWN) MG_ERROR(("Network is down"));
  ------------------
  |  | 1014|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (5013:9): [True: 0, False: 5.44k]
  ------------------
 5014|  5.44k|    mg_tcpip_call(ifp, MG_TCPIP_EV_TIMER_1S, NULL);
 5015|  5.44k|  }
 5016|  5.44k|  if (ifp->state == MG_TCPIP_STATE_DOWN) return;
  ------------------
  |  | 2793|  5.44k|#define MG_TCPIP_STATE_DOWN 0   // Interface is down
  ------------------
  |  Branch (5016:7): [True: 0, False: 5.44k]
  ------------------
 5017|       |
 5018|       |  // DHCP RFC-2131 (4.4)
 5019|  5.44k|  if (ifp->enable_dhcp_client && expired_1000ms) {
  ------------------
  |  Branch (5019:7): [True: 0, False: 5.44k]
  |  Branch (5019:34): [True: 0, False: 0]
  ------------------
 5020|      0|    if (ifp->state == MG_TCPIP_STATE_UP) {
  ------------------
  |  | 2794|      0|#define MG_TCPIP_STATE_UP 1     // Interface is up
  ------------------
  |  Branch (5020:9): [True: 0, False: 0]
  ------------------
 5021|      0|      tx_dhcp_discover(ifp);  // INIT (4.4.1)
 5022|      0|    } else if (ifp->state == MG_TCPIP_STATE_READY &&
  ------------------
  |  | 2797|      0|#define MG_TCPIP_STATE_READY 4  // Interface has fully come up, ready to work
  ------------------
  |  Branch (5022:16): [True: 0, False: 0]
  ------------------
 5023|      0|               ifp->lease_expire > 0) {  // BOUND / RENEWING / REBINDING
  ------------------
  |  Branch (5023:16): [True: 0, False: 0]
  ------------------
 5024|      0|      if (ifp->now >= ifp->lease_expire) {
  ------------------
  |  Branch (5024:11): [True: 0, False: 0]
  ------------------
 5025|      0|        ifp->state = MG_TCPIP_STATE_UP, ifp->ip = 0;  // expired, release IP
  ------------------
  |  | 2794|      0|#define MG_TCPIP_STATE_UP 1     // Interface is up
  ------------------
 5026|      0|        onstatechange(ifp);
 5027|      0|      } else if (ifp->now + 30UL * 60UL * 1000UL > ifp->lease_expire &&
  ------------------
  |  Branch (5027:18): [True: 0, False: 0]
  ------------------
 5028|      0|                 ((ifp->now / 1000) % 60) == 0) {
  ------------------
  |  Branch (5028:18): [True: 0, False: 0]
  ------------------
 5029|       |        // hack: 30 min before deadline, try to rebind (4.3.6) every min
 5030|      0|        tx_dhcp_request_re(ifp, (uint8_t *) broadcast, ifp->ip, 0xffffffff);
 5031|      0|      }  // TODO(): Handle T1 (RENEWING) and T2 (REBINDING) (4.4.5)
 5032|      0|    }
 5033|      0|  }
 5034|       |
 5035|       |  // Read data from the network
 5036|  5.44k|  if (ifp->driver->rx != NULL) {  // Polling driver. We must call it
  ------------------
  |  Branch (5036:7): [True: 5.44k, False: 0]
  ------------------
 5037|  5.44k|    size_t len =
 5038|  5.44k|        ifp->driver->rx(ifp->recv_queue.buf, ifp->recv_queue.size, ifp);
 5039|  5.44k|    if (len > 0) {
  ------------------
  |  Branch (5039:9): [True: 0, False: 5.44k]
  ------------------
 5040|      0|      ifp->nrecv++;
 5041|      0|      mg_tcpip_rx(ifp, ifp->recv_queue.buf, len);
 5042|      0|    }
 5043|  5.44k|  } else {  // Interrupt-based driver. Fills recv queue itself
 5044|      0|    char *buf;
 5045|      0|    size_t len = mg_queue_next(&ifp->recv_queue, &buf);
 5046|      0|    if (len > 0) {
  ------------------
  |  Branch (5046:9): [True: 0, False: 0]
  ------------------
 5047|      0|      mg_tcpip_rx(ifp, buf, len);
 5048|      0|      mg_queue_del(&ifp->recv_queue, len);
 5049|      0|    }
 5050|      0|  }
 5051|       |
 5052|       |  // Process timeouts
 5053|  10.8k|  for (c = ifp->mgr->conns; c != NULL; c = c->next) {
  ------------------
  |  Branch (5053:29): [True: 5.44k, False: 5.44k]
  ------------------
 5054|  5.44k|    if ((c->is_udp && !c->is_arplooking) || c->is_listening || c->is_resolving)
  ------------------
  |  Branch (5054:10): [True: 0, False: 5.44k]
  |  Branch (5054:23): [True: 0, False: 0]
  |  Branch (5054:45): [True: 0, False: 5.44k]
  |  Branch (5054:64): [True: 0, False: 5.44k]
  ------------------
 5055|      0|      continue;
 5056|  5.44k|    struct connstate *s = (struct connstate *) (c + 1);
 5057|  5.44k|    uint32_t rem_ip;
 5058|  5.44k|    memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
 5059|  5.44k|    if (ifp->now > s->timer) {
  ------------------
  |  Branch (5059:9): [True: 5.44k, False: 0]
  ------------------
 5060|  5.44k|      if (s->ttype == MIP_TTYPE_ARP) {
  ------------------
  |  | 4106|  5.44k|#define MIP_TTYPE_ARP 2        // ARP resolve sent, waiting for response
  ------------------
  |  Branch (5060:11): [True: 0, False: 5.44k]
  ------------------
 5061|      0|        mg_error(c, "ARP timeout");
 5062|  5.44k|      } else if (c->is_udp) {
  ------------------
  |  Branch (5062:18): [True: 0, False: 5.44k]
  ------------------
 5063|      0|        continue;
 5064|  5.44k|      } else if (s->ttype == MIP_TTYPE_ACK && s->acked != s->ack) {
  ------------------
  |  | 4105|  10.8k|#define MIP_TTYPE_ACK 1        // Peer sent us data, we have to ack it soon
  ------------------
  |  Branch (5064:18): [True: 0, False: 5.44k]
  |  Branch (5064:47): [True: 0, False: 0]
  ------------------
 5065|      0|        MG_VERBOSE(("%lu ack %x %x", c->id, s->seq, s->ack));
  ------------------
  |  | 1017|      0|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5066|      0|        tx_tcp(ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
  ------------------
  |  | 4181|      0|#define TH_ACK 0x10
  ------------------
 5067|      0|               mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
  ------------------
  |  | 1114|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
                             mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
  ------------------
  |  | 1114|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
 5068|      0|        s->acked = s->ack;
 5069|  5.44k|      } else if (s->ttype == MIP_TTYPE_SYN) {
  ------------------
  |  | 4107|  5.44k|#define MIP_TTYPE_SYN 3        // SYN sent, waiting for response
  ------------------
  |  Branch (5069:18): [True: 5.44k, False: 0]
  ------------------
 5070|  5.44k|        mg_error(c, "Connection timeout");
 5071|  5.44k|      } else if (s->ttype == MIP_TTYPE_FIN) {
  ------------------
  |  | 4108|      0|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
  |  Branch (5071:18): [True: 0, False: 0]
  ------------------
 5072|      0|        c->is_closing = 1;
 5073|      0|        continue;
 5074|      0|      } else {
 5075|      0|        if (s->tmiss++ > 2) {
  ------------------
  |  Branch (5075:13): [True: 0, False: 0]
  ------------------
 5076|      0|          mg_error(c, "keepalive");
 5077|      0|        } else {
 5078|      0|          MG_VERBOSE(("%lu keepalive", c->id));
  ------------------
  |  | 1017|      0|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5079|      0|          tx_tcp(ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
  ------------------
  |  | 4181|      0|#define TH_ACK 0x10
  ------------------
 5080|      0|                 mg_htonl(s->seq - 1), mg_htonl(s->ack), NULL, 0);
  ------------------
  |  | 1114|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
                               mg_htonl(s->seq - 1), mg_htonl(s->ack), NULL, 0);
  ------------------
  |  | 1114|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
 5081|      0|        }
 5082|      0|      }
 5083|       |
 5084|  5.44k|      settmout(c, MIP_TTYPE_KEEPALIVE);
  ------------------
  |  | 4104|  5.44k|#define MIP_TTYPE_KEEPALIVE 0  // Connection is idle for long, send keepalive
  ------------------
 5085|  5.44k|    }
 5086|  5.44k|  }
 5087|  5.44k|}
fuzz.c:_ZL13onstatechangeP11mg_tcpip_if:
 4285|  5.44k|static void onstatechange(struct mg_tcpip_if *ifp) {
 4286|  5.44k|  if (ifp->state == MG_TCPIP_STATE_READY) {
  ------------------
  |  | 2797|  5.44k|#define MG_TCPIP_STATE_READY 4  // Interface has fully come up, ready to work
  ------------------
  |  Branch (4286:7): [True: 0, False: 5.44k]
  ------------------
 4287|      0|    MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip));
  ------------------
  |  | 1015|      0|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4288|      0|    MG_INFO(("       GW: %M", mg_print_ip4, &ifp->gw));
  ------------------
  |  | 1015|      0|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4289|      0|    MG_INFO(("      MAC: %M", mg_print_mac, &ifp->mac));
  ------------------
  |  | 1015|      0|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4290|  5.44k|  } else if (ifp->state == MG_TCPIP_STATE_IP) {
  ------------------
  |  | 2796|  5.44k|#define MG_TCPIP_STATE_IP 3     // Interface is up and has an IP assigned
  ------------------
  |  Branch (4290:14): [True: 5.44k, False: 0]
  ------------------
 4291|  5.44k|    MG_ERROR(("Got IP"));
  ------------------
  |  | 1014|  5.44k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|  5.44k|  do {                      \
  |  |  |  | 1010|  5.44k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|  5.44k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4292|  5.44k|    mg_tcpip_arp_request(ifp, ifp->gw, NULL);  // unsolicited GW ARP request
 4293|  5.44k|  } else if (ifp->state == MG_TCPIP_STATE_UP) {
  ------------------
  |  | 2794|      0|#define MG_TCPIP_STATE_UP 1     // Interface is up
  ------------------
  |  Branch (4293:14): [True: 0, False: 0]
  ------------------
 4294|      0|    MG_ERROR(("Link up"));
  ------------------
  |  | 1014|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4295|      0|    srand((unsigned int) mg_millis());
 4296|      0|  } else if (ifp->state == MG_TCPIP_STATE_DOWN) {
  ------------------
  |  | 2793|      0|#define MG_TCPIP_STATE_DOWN 0   // Interface is down
  ------------------
  |  Branch (4296:14): [True: 0, False: 0]
  ------------------
 4297|      0|    MG_ERROR(("Link down"));
  ------------------
  |  | 1014|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4298|      0|  }
 4299|  5.44k|  mg_tcpip_call(ifp, MG_TCPIP_EV_ST_CHG, &ifp->state);
 4300|  5.44k|}
fuzz.c:_ZL13mg_tcpip_callP11mg_tcpip_ifiPv:
 4223|  11.4k|static void mg_tcpip_call(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
 4224|  11.4k|  if (ifp->fn != NULL) ifp->fn(ifp, ev, ev_data);
  ------------------
  |  Branch (4224:7): [True: 0, False: 11.4k]
  ------------------
 4225|  11.4k|}
fuzz.c:_ZL9can_writeP13mg_connection:
 5229|  5.44k|static bool can_write(struct mg_connection *c) {
 5230|  5.44k|  return c->is_connecting == 0 && c->is_resolving == 0 && c->send.len > 0 &&
  ------------------
  |  Branch (5230:10): [True: 0, False: 5.44k]
  |  Branch (5230:35): [True: 0, False: 0]
  |  Branch (5230:59): [True: 0, False: 0]
  ------------------
 5231|  5.44k|         c->is_tls_hs == 0 && c->is_arplooking == 0;
  ------------------
  |  Branch (5231:10): [True: 0, False: 0]
  |  Branch (5231:31): [True: 0, False: 0]
  ------------------
 5232|  5.44k|}
fuzz.c:_ZL12init_closureP13mg_connection:
 5211|  1.73k|static void init_closure(struct mg_connection *c) {
 5212|  1.73k|  struct connstate *s = (struct connstate *) (c + 1);
 5213|  1.73k|  if (c->is_udp == false && c->is_listening == false &&
  ------------------
  |  Branch (5213:7): [True: 1.73k, False: 0]
  |  Branch (5213:29): [True: 1.73k, False: 0]
  ------------------
 5214|  1.73k|      c->is_connecting == false) {  // For TCP conns,
  ------------------
  |  Branch (5214:7): [True: 0, False: 1.73k]
  ------------------
 5215|      0|    uint32_t rem_ip;
 5216|      0|    memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
 5217|      0|    tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_FIN | TH_ACK, c->loc.port,
  ------------------
  |  | 4177|      0|#define TH_FIN 0x01
  ------------------
                  tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_FIN | TH_ACK, c->loc.port,
  ------------------
  |  | 4181|      0|#define TH_ACK 0x10
  ------------------
 5218|      0|           c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
  ------------------
  |  | 1114|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
                         c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
  ------------------
  |  | 1114|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
 5219|      0|    settmout(c, MIP_TTYPE_FIN);
  ------------------
  |  | 4108|      0|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
 5220|      0|  }
 5221|  1.73k|}
fuzz.c:_ZL10close_connP13mg_connection:
 5223|  5.44k|static void close_conn(struct mg_connection *c) {
 5224|  5.44k|  struct connstate *s = (struct connstate *) (c + 1);
 5225|  5.44k|  mg_iobuf_free(&s->raw);  // For TLS connections, release raw data
 5226|  5.44k|  mg_close_conn(c);
 5227|  5.44k|}
fuzz.c:_ZL20mg_pfn_iobuf_privatecPvb:
 6924|   927M|static void mg_pfn_iobuf_private(char ch, void *param, bool expand) {
 6925|   927M|  struct mg_iobuf *io = (struct mg_iobuf *) param;
 6926|   927M|  if (expand && io->len + 2 > io->size) mg_iobuf_resize(io, io->len + 2);
  ------------------
  |  Branch (6926:7): [True: 810M, False: 117M]
  |  Branch (6926:17): [True: 43.3k, False: 810M]
  ------------------
 6927|   927M|  if (io->len + 2 <= io->size) {
  ------------------
  |  Branch (6927:7): [True: 927M, False: 33.6k]
  ------------------
 6928|   927M|    io->buf[io->len++] = (uint8_t) ch;
 6929|   927M|    io->buf[io->len] = 0;
 6930|   927M|  } else if (io->len < io->size) {
  ------------------
  |  Branch (6930:14): [True: 3.75k, False: 29.8k]
  ------------------
 6931|  3.75k|    io->buf[io->len++] = 0;  // Guarantee to 0-terminate
 6932|  3.75k|  }
 6933|   927M|}
fuzz.c:_ZL23mg_putchar_iobuf_staticcPv:
 6935|   117M|static void mg_putchar_iobuf_static(char ch, void *param) {
 6936|   117M|  mg_pfn_iobuf_private(ch, param, false);
 6937|   117M|}
fuzz.c:_ZL12gettimestampPKj:
 7851|    633|static int64_t gettimestamp(const uint32_t *data) {
 7852|    633|  uint32_t sec = mg_ntohl(data[0]), frac = mg_ntohl(data[1]);
 7853|    633|  if (sec) sec -= SNTP_TIME_OFFSET;
  ------------------
  |  | 7842|    601|#define SNTP_TIME_OFFSET 2208988800U  // (1970 - 1900) in seconds
  ------------------
  |  Branch (7853:7): [True: 601, False: 32]
  ------------------
 7854|    633|  return ((int64_t) sec) * 1000 + (int64_t) (frac / SNTP_MAX_FRAC * 1000.0);
  ------------------
  |  | 7843|    633|#define SNTP_MAX_FRAC 4294967295.0    // 2 ** 32 - 1
  ------------------
 7855|    633|}
fuzz.c:_ZL7mg_tolcc:
 8780|  2.77M|static int mg_tolc(char c) {
 8781|  2.77M|  return (c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : c;
  ------------------
  |  Branch (8781:11): [True: 1.50M, False: 1.27M]
  |  Branch (8781:23): [True: 1.36M, False: 141k]
  ------------------
 8782|  2.77M|}
fuzz.c:_ZL8urlparsePKc:
18853|  10.8k|static struct url urlparse(const char *url) {
18854|  10.8k|  size_t i;
18855|  10.8k|  struct url u;
18856|  10.8k|  memset(&u, 0, sizeof(u));
18857|   250k|  for (i = 0; url[i] != '\0'; i++) {
  ------------------
  |  Branch (18857:15): [True: 239k, False: 10.8k]
  ------------------
18858|   239k|    if (url[i] == '/' && i > 0 && u.host == 0 && url[i - 1] == '/') {
  ------------------
  |  Branch (18858:9): [True: 21.7k, False: 217k]
  |  Branch (18858:26): [True: 21.7k, False: 0]
  |  Branch (18858:35): [True: 21.7k, False: 0]
  |  Branch (18858:50): [True: 10.8k, False: 10.8k]
  ------------------
18859|  10.8k|      u.host = i + 1;
18860|  10.8k|      u.port = 0;
18861|   228k|    } else if (url[i] == ']') {
  ------------------
  |  Branch (18861:16): [True: 0, False: 228k]
  ------------------
18862|      0|      u.port = 0;  // IPv6 URLs, like http://[::1]/bar
18863|   228k|    } else if (url[i] == ':' && u.port == 0 && u.uri == 0) {
  ------------------
  |  Branch (18863:16): [True: 21.7k, False: 206k]
  |  Branch (18863:33): [True: 21.7k, False: 0]
  |  Branch (18863:48): [True: 21.7k, False: 0]
  ------------------
18864|  21.7k|      u.port = i + 1;
18865|   206k|    } else if (url[i] == '@' && u.user == 0 && u.pass == 0 && u.uri == 0) {
  ------------------
  |  Branch (18865:16): [True: 0, False: 206k]
  |  Branch (18865:33): [True: 0, False: 0]
  |  Branch (18865:48): [True: 0, False: 0]
  |  Branch (18865:63): [True: 0, False: 0]
  ------------------
18866|      0|      u.user = u.host;
18867|      0|      u.pass = u.port;
18868|      0|      u.host = i + 1;
18869|      0|      u.port = 0;
18870|   206k|    } else if (url[i] == '/' && u.host && u.uri == 0) {
  ------------------
  |  Branch (18870:16): [True: 10.8k, False: 195k]
  |  Branch (18870:33): [True: 0, False: 10.8k]
  |  Branch (18870:43): [True: 0, False: 0]
  ------------------
18871|      0|      u.uri = i;
18872|      0|    }
18873|   239k|  }
18874|  10.8k|  u.end = i;
18875|       |#if 0
18876|       |  printf("[%s] %d %d %d %d %d\n", url, u.user, u.pass, u.host, u.port, u.uri);
18877|       |#endif
18878|  10.8k|  return u;
18879|  10.8k|}
fuzz.c:_ZL11mg_tcpip_rxP11mg_tcpip_ifPvm:
 4934|  5.44k|static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) {
 4935|  5.44k|  struct pkt pkt;
 4936|  5.44k|  memset(&pkt, 0, sizeof(pkt));
 4937|  5.44k|  pkt.raw.buf = (char *) buf;
 4938|  5.44k|  pkt.raw.len = len;
 4939|  5.44k|  pkt.eth = (struct eth *) buf;
 4940|       |  // mg_hexdump(buf, len > 16 ? 16: len);
 4941|  5.44k|  if (pkt.raw.len < sizeof(*pkt.eth)) return;  // Truncated - runt?
  ------------------
  |  Branch (4941:7): [True: 1.69k, False: 3.74k]
  ------------------
 4942|  3.74k|  if (ifp->enable_mac_check &&
  ------------------
  |  Branch (4942:7): [True: 0, False: 3.74k]
  ------------------
 4943|  3.74k|      memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 &&
  ------------------
  |  Branch (4943:7): [True: 0, False: 0]
  ------------------
 4944|  3.74k|      memcmp(pkt.eth->dst, broadcast, sizeof(pkt.eth->dst)) != 0)
  ------------------
  |  Branch (4944:7): [True: 0, False: 0]
  ------------------
 4945|      0|    return;
 4946|  3.74k|  if (ifp->enable_crc32_check && len > 4) {
  ------------------
  |  Branch (4946:7): [True: 0, False: 3.74k]
  |  Branch (4946:34): [True: 0, False: 0]
  ------------------
 4947|      0|    len -= 4;  // TODO(scaprile): check on bigendian
 4948|      0|    uint32_t crc = mg_crc32(0, (const char *) buf, len);
 4949|      0|    if (memcmp((void *) ((size_t) buf + len), &crc, sizeof(crc))) return;
  ------------------
  |  Branch (4949:9): [True: 0, False: 0]
  ------------------
 4950|      0|  }
 4951|  3.74k|  if (pkt.eth->type == mg_htons(0x806)) {
  ------------------
  |  | 1113|  3.74k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (4951:7): [True: 903, False: 2.84k]
  ------------------
 4952|    903|    pkt.arp = (struct arp *) (pkt.eth + 1);
 4953|    903|    if (sizeof(*pkt.eth) + sizeof(*pkt.arp) > pkt.raw.len) return;  // Truncated
  ------------------
  |  Branch (4953:9): [True: 306, False: 597]
  ------------------
 4954|    597|    mg_tcpip_call(ifp, MG_TCPIP_EV_ARP, &pkt.raw);
 4955|    597|    rx_arp(ifp, &pkt);
 4956|  2.84k|  } else if (pkt.eth->type == mg_htons(0x86dd)) {
  ------------------
  |  | 1113|  2.84k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (4956:14): [True: 903, False: 1.94k]
  ------------------
 4957|    903|    pkt.ip6 = (struct ip6 *) (pkt.eth + 1);
 4958|    903|    if (pkt.raw.len < sizeof(*pkt.eth) + sizeof(*pkt.ip6)) return;  // Truncated
  ------------------
  |  Branch (4958:9): [True: 391, False: 512]
  ------------------
 4959|    512|    if ((pkt.ip6->ver >> 4) != 0x6) return;                         // Not IP
  ------------------
  |  Branch (4959:9): [True: 395, False: 117]
  ------------------
 4960|    117|    mkpay(&pkt, pkt.ip6 + 1);
 4961|    117|    rx_ip6(ifp, &pkt);
 4962|  1.94k|  } else if (pkt.eth->type == mg_htons(0x800)) {
  ------------------
  |  | 1113|  1.94k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (4962:14): [True: 1.80k, False: 135]
  ------------------
 4963|  1.80k|    pkt.ip = (struct ip *) (pkt.eth + 1);
 4964|  1.80k|    if (pkt.raw.len < sizeof(*pkt.eth) + sizeof(*pkt.ip)) return;  // Truncated
  ------------------
  |  Branch (4964:9): [True: 389, False: 1.41k]
  ------------------
 4965|       |    // Truncate frame to what IP header tells us
 4966|  1.41k|    if ((size_t) mg_ntohs(pkt.ip->len) + sizeof(struct eth) < pkt.raw.len) {
  ------------------
  |  Branch (4966:9): [True: 292, False: 1.12k]
  ------------------
 4967|    292|      pkt.raw.len = (size_t) mg_ntohs(pkt.ip->len) + sizeof(struct eth);
 4968|    292|    }
 4969|  1.41k|    if (pkt.raw.len < sizeof(*pkt.eth) + sizeof(*pkt.ip)) return;  // Truncated
  ------------------
  |  Branch (4969:9): [True: 32, False: 1.38k]
  ------------------
 4970|  1.38k|    if ((pkt.ip->ver >> 4) != 4) return;                           // Not IP
  ------------------
  |  Branch (4970:9): [True: 1.19k, False: 194]
  ------------------
 4971|    194|    mkpay(&pkt, pkt.ip + 1);
 4972|    194|    rx_ip(ifp, &pkt);
 4973|    194|  } else {
 4974|    135|    MG_DEBUG(("Unknown eth type %x", mg_htons(pkt.eth->type)));
  ------------------
  |  | 1016|    135|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1009|    135|  do {                      \
  |  |  |  | 1010|    135|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|    135|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4975|    135|    if (mg_log_level >= MG_LL_VERBOSE) mg_hexdump(buf, len >= 32 ? 32 : len);
  ------------------
  |  Branch (4975:9): [True: 0, False: 135]
  |  Branch (4975:56): [True: 0, False: 0]
  ------------------
 4976|    135|  }
 4977|  3.74k|}
fuzz.c:_ZL6rx_arpP11mg_tcpip_ifP3pkt:
 4420|    597|static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
 4421|    597|  if (pkt->arp->op == mg_htons(1) && pkt->arp->tpa == ifp->ip) {
  ------------------
  |  | 1113|  1.19k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (4421:7): [True: 12, False: 585]
  |  Branch (4421:38): [True: 0, False: 12]
  ------------------
 4422|       |    // ARP request. Make a response, then send
 4423|       |    // MG_DEBUG(("ARP op %d %M: %M", mg_ntohs(pkt->arp->op), mg_print_ip4,
 4424|       |    //          &pkt->arp->spa, mg_print_ip4, &pkt->arp->tpa));
 4425|      0|    struct eth *eth = (struct eth *) ifp->tx.buf;
 4426|      0|    struct arp *arp = (struct arp *) (eth + 1);
 4427|      0|    memcpy(eth->dst, pkt->eth->src, sizeof(eth->dst));
 4428|      0|    memcpy(eth->src, ifp->mac, sizeof(eth->src));
 4429|      0|    eth->type = mg_htons(0x806);
  ------------------
  |  | 1113|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
 4430|      0|    *arp = *pkt->arp;
 4431|      0|    arp->op = mg_htons(2);
  ------------------
  |  | 1113|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
 4432|      0|    memcpy(arp->tha, pkt->arp->sha, sizeof(pkt->arp->tha));
 4433|      0|    memcpy(arp->sha, ifp->mac, sizeof(pkt->arp->sha));
 4434|      0|    arp->tpa = pkt->arp->spa;
 4435|      0|    arp->spa = ifp->ip;
 4436|      0|    MG_DEBUG(("ARP: tell %M we're %M", mg_print_ip4, &arp->tpa, mg_print_mac,
  ------------------
  |  | 1016|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4437|      0|              &ifp->mac));
 4438|      0|    ether_output(ifp, PDIFF(eth, arp + 1));
  ------------------
  |  | 4085|      0|#define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a))))
  ------------------
 4439|    597|  } else if (pkt->arp->op == mg_htons(2)) {
  ------------------
  |  | 1113|    597|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (4439:14): [True: 2, False: 595]
  ------------------
 4440|      2|    if (memcmp(pkt->arp->tha, ifp->mac, sizeof(pkt->arp->tha)) != 0) return;
  ------------------
  |  Branch (4440:9): [True: 2, False: 0]
  ------------------
 4441|      0|    if (pkt->arp->spa == ifp->gw) {
  ------------------
  |  Branch (4441:9): [True: 0, False: 0]
  ------------------
 4442|       |      // Got response for the GW ARP request. Set ifp->gwmac and IP -> READY
 4443|      0|      memcpy(ifp->gwmac, pkt->arp->sha, sizeof(ifp->gwmac));
 4444|      0|      if (ifp->state == MG_TCPIP_STATE_IP) {
  ------------------
  |  | 2796|      0|#define MG_TCPIP_STATE_IP 3     // Interface is up and has an IP assigned
  ------------------
  |  Branch (4444:11): [True: 0, False: 0]
  ------------------
 4445|      0|        ifp->state = MG_TCPIP_STATE_READY;
  ------------------
  |  | 2797|      0|#define MG_TCPIP_STATE_READY 4  // Interface has fully come up, ready to work
  ------------------
 4446|      0|        onstatechange(ifp);
 4447|      0|      }
 4448|      0|    } else {
 4449|      0|      struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
 4450|      0|      if (c != NULL && c->is_arplooking) {
  ------------------
  |  Branch (4450:11): [True: 0, False: 0]
  |  Branch (4450:24): [True: 0, False: 0]
  ------------------
 4451|      0|        struct connstate *s = (struct connstate *) (c + 1);
 4452|      0|        memcpy(s->mac, pkt->arp->sha, sizeof(s->mac));
 4453|      0|        MG_DEBUG(("%lu ARP resolved %M -> %M", c->id, mg_print_ip4, c->rem.ip,
  ------------------
  |  | 1016|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4454|      0|                  mg_print_mac, s->mac));
 4455|      0|        c->is_arplooking = 0;
 4456|      0|        mac_resolved(c);
 4457|      0|      }
 4458|      0|    }
 4459|      0|  }
 4460|    597|}
fuzz.c:_ZL7getpeerP6mg_mgrP3pktb:
 4404|    122|                                     bool lsn) {
 4405|    122|  struct mg_connection *c = NULL;
 4406|    122|  for (c = mgr->conns; c != NULL; c = c->next) {
  ------------------
  |  Branch (4406:24): [True: 0, False: 122]
  ------------------
 4407|      0|    if (c->is_arplooking && pkt->arp &&
  ------------------
  |  Branch (4407:9): [True: 0, False: 0]
  |  Branch (4407:29): [True: 0, False: 0]
  ------------------
 4408|      0|        memcmp(&pkt->arp->spa, c->rem.ip, sizeof(pkt->arp->spa)) == 0)
  ------------------
  |  Branch (4408:9): [True: 0, False: 0]
  ------------------
 4409|      0|      break;
 4410|      0|    if (c->is_udp && pkt->udp && c->loc.port == pkt->udp->dport) break;
  ------------------
  |  Branch (4410:9): [True: 0, False: 0]
  |  Branch (4410:22): [True: 0, False: 0]
  |  Branch (4410:34): [True: 0, False: 0]
  ------------------
 4411|      0|    if (!c->is_udp && pkt->tcp && c->loc.port == pkt->tcp->dport &&
  ------------------
  |  Branch (4411:9): [True: 0, False: 0]
  |  Branch (4411:23): [True: 0, False: 0]
  |  Branch (4411:35): [True: 0, False: 0]
  ------------------
 4412|      0|        lsn == c->is_listening && (lsn || c->rem.port == pkt->tcp->sport))
  ------------------
  |  Branch (4412:9): [True: 0, False: 0]
  |  Branch (4412:36): [True: 0, False: 0]
  |  Branch (4412:43): [True: 0, False: 0]
  ------------------
 4413|      0|      break;
 4414|      0|  }
 4415|    122|  return c;
 4416|    122|}
fuzz.c:_ZL5mkpayP3pktPv:
 4229|    438|static void mkpay(struct pkt *pkt, void *p) {
 4230|    438|  pkt->pay =
 4231|    438|      mg_str_n((char *) p, (size_t) (&pkt->raw.buf[pkt->raw.len] - (char *) p));
 4232|    438|}
fuzz.c:_ZL6rx_ip6P11mg_tcpip_ifP3pkt:
 4918|    117|static void rx_ip6(struct mg_tcpip_if *ifp, struct pkt *pkt) {
 4919|       |  // MG_DEBUG(("IP %d", (int) len));
 4920|    117|  if (pkt->ip6->proto == 1 || pkt->ip6->proto == 58) {
  ------------------
  |  Branch (4920:7): [True: 0, False: 117]
  |  Branch (4920:31): [True: 37, False: 80]
  ------------------
 4921|     37|    pkt->icmp = (struct icmp *) (pkt->ip6 + 1);
 4922|     37|    if (pkt->pay.len < sizeof(*pkt->icmp)) return;
  ------------------
  |  Branch (4922:9): [True: 3, False: 34]
  ------------------
 4923|     34|    mkpay(pkt, pkt->icmp + 1);
 4924|     34|    rx_icmp(ifp, pkt);
 4925|     80|  } else if (pkt->ip6->proto == 17) {
  ------------------
  |  Branch (4925:14): [True: 5, False: 75]
  ------------------
 4926|      5|    pkt->udp = (struct udp *) (pkt->ip6 + 1);
 4927|      5|    if (pkt->pay.len < sizeof(*pkt->udp)) return;
  ------------------
  |  Branch (4927:9): [True: 1, False: 4]
  ------------------
 4928|       |    // MG_DEBUG(("  UDP %u %u -> %u", len, mg_htons(udp->sport),
 4929|       |    // mg_htons(udp->dport)));
 4930|      4|    mkpay(pkt, pkt->udp + 1);
 4931|      4|  }
 4932|    117|}
fuzz.c:_ZL7rx_icmpP11mg_tcpip_ifP3pkt:
 4462|    109|static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
 4463|       |  // MG_DEBUG(("ICMP %d", (int) len));
 4464|    109|  if (pkt->icmp->type == 8 && pkt->ip != NULL && pkt->ip->dst == ifp->ip) {
  ------------------
  |  Branch (4464:7): [True: 73, False: 36]
  |  Branch (4464:31): [True: 73, False: 0]
  |  Branch (4464:50): [True: 39, False: 34]
  ------------------
 4465|     39|    size_t hlen = sizeof(struct eth) + sizeof(struct ip) + sizeof(struct icmp);
 4466|     39|    size_t space = ifp->tx.len - hlen, plen = pkt->pay.len;
 4467|     39|    if (plen > space) plen = space;
  ------------------
  |  Branch (4467:9): [True: 10, False: 29]
  ------------------
 4468|     39|    struct ip *ip = tx_ip(ifp, pkt->eth->src, 1, ifp->ip, pkt->ip->src,
 4469|     39|                          sizeof(struct icmp) + plen);
 4470|     39|    struct icmp *icmp = (struct icmp *) (ip + 1);
 4471|     39|    memset(icmp, 0, sizeof(*icmp));        // Set csum to 0
 4472|     39|    memcpy(icmp + 1, pkt->pay.buf, plen);  // Copy RX payload to TX
 4473|     39|    icmp->csum = ipcsum(icmp, sizeof(*icmp) + plen);
 4474|     39|    ether_output(ifp, hlen + plen);
 4475|     39|  }
 4476|    109|}
fuzz.c:_ZL5rx_ipP11mg_tcpip_ifP3pkt:
 4874|    194|static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) {
 4875|    194|  uint16_t frag = mg_ntohs(pkt->ip->frag);
 4876|    194|  if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) {
  ------------------
  |  | 4134|    388|#define IP_MORE_FRAGS_MSK 0x2000
  ------------------
                if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) {
  ------------------
  |  | 4133|    150|#define IP_FRAG_OFFSET_MSK 0x1fff
  ------------------
  |  Branch (4876:7): [True: 44, False: 150]
  |  Branch (4876:35): [True: 50, False: 100]
  ------------------
 4877|     94|    if (pkt->ip->proto == 17) pkt->udp = (struct udp *) (pkt->ip + 1);
  ------------------
  |  Branch (4877:9): [True: 1, False: 93]
  ------------------
 4878|     94|    if (pkt->ip->proto == 6) pkt->tcp = (struct tcp *) (pkt->ip + 1);
  ------------------
  |  Branch (4878:9): [True: 1, False: 93]
  ------------------
 4879|     94|    struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
 4880|     94|    if (c) mg_error(c, "Received fragmented packet");
  ------------------
  |  Branch (4880:9): [True: 0, False: 94]
  ------------------
 4881|    100|  } else if (pkt->ip->proto == 1) {
  ------------------
  |  Branch (4881:14): [True: 77, False: 23]
  ------------------
 4882|     77|    pkt->icmp = (struct icmp *) (pkt->ip + 1);
 4883|     77|    if (pkt->pay.len < sizeof(*pkt->icmp)) return;
  ------------------
  |  Branch (4883:9): [True: 2, False: 75]
  ------------------
 4884|     75|    mkpay(pkt, pkt->icmp + 1);
 4885|     75|    rx_icmp(ifp, pkt);
 4886|     75|  } else if (pkt->ip->proto == 17) {
  ------------------
  |  Branch (4886:14): [True: 0, False: 23]
  ------------------
 4887|      0|    pkt->udp = (struct udp *) (pkt->ip + 1);
 4888|      0|    if (pkt->pay.len < sizeof(*pkt->udp)) return;
  ------------------
  |  Branch (4888:9): [True: 0, False: 0]
  ------------------
 4889|      0|    mkpay(pkt, pkt->udp + 1);
 4890|      0|    MG_VERBOSE(("UDP %M:%hu -> %M:%hu len %u", mg_print_ip4, &pkt->ip->src,
  ------------------
  |  | 1017|      0|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1009|      0|  do {                      \
  |  |  |  | 1010|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4891|      0|                mg_ntohs(pkt->udp->sport), mg_print_ip4, &pkt->ip->dst,
 4892|      0|                mg_ntohs(pkt->udp->dport), (int) pkt->pay.len));
 4893|      0|    if (ifp->enable_dhcp_client && pkt->udp->dport == mg_htons(68)) {
  ------------------
  |  | 1113|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (4893:9): [True: 0, False: 0]
  |  Branch (4893:36): [True: 0, False: 0]
  ------------------
 4894|      0|      pkt->dhcp = (struct dhcp *) (pkt->udp + 1);
 4895|      0|      mkpay(pkt, pkt->dhcp + 1);
 4896|      0|      rx_dhcp_client(ifp, pkt);
 4897|      0|    } else if (ifp->enable_dhcp_server && pkt->udp->dport == mg_htons(67)) {
  ------------------
  |  | 1113|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (4897:16): [True: 0, False: 0]
  |  Branch (4897:43): [True: 0, False: 0]
  ------------------
 4898|      0|      pkt->dhcp = (struct dhcp *) (pkt->udp + 1);
 4899|      0|      mkpay(pkt, pkt->dhcp + 1);
 4900|      0|      rx_dhcp_server(ifp, pkt);
 4901|      0|    } else {
 4902|      0|      rx_udp(ifp, pkt);
 4903|      0|    }
 4904|     23|  } else if (pkt->ip->proto == 6) {
  ------------------
  |  Branch (4904:14): [True: 18, False: 5]
  ------------------
 4905|     18|    pkt->tcp = (struct tcp *) (pkt->ip + 1);
 4906|     18|    if (pkt->pay.len < sizeof(*pkt->tcp)) return;
  ------------------
  |  Branch (4906:9): [True: 4, False: 14]
  ------------------
 4907|     14|    mkpay(pkt, pkt->tcp + 1);
 4908|     14|    uint16_t iplen = mg_ntohs(pkt->ip->len);
 4909|     14|    uint16_t off = (uint16_t) (sizeof(*pkt->ip) + ((pkt->tcp->off >> 4) * 4U));
 4910|     14|    if (iplen >= off) pkt->pay.len = (size_t) (iplen - off);
  ------------------
  |  Branch (4910:9): [True: 13, False: 1]
  ------------------
 4911|     14|    MG_VERBOSE(("TCP %M:%hu -> %M:%hu len %u", mg_print_ip4, &pkt->ip->src,
  ------------------
  |  | 1017|     14|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1009|     14|  do {                      \
  |  |  |  | 1010|     14|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1010:9): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  |  | 1011|     14|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1011:12): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4912|     14|                mg_ntohs(pkt->tcp->sport), mg_print_ip4, &pkt->ip->dst,
 4913|     14|                mg_ntohs(pkt->tcp->dport), (int) pkt->pay.len));
 4914|     14|    rx_tcp(ifp, pkt);
 4915|     14|  }
 4916|    194|}
fuzz.c:_ZL6rx_tcpP11mg_tcpip_ifP3pkt:
 4824|     14|static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
 4825|     14|  struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
 4826|     14|  struct connstate *s = c == NULL ? NULL : (struct connstate *) (c + 1);
  ------------------
  |  Branch (4826:25): [True: 14, False: 0]
  ------------------
 4827|       |#if 0
 4828|       |  MG_INFO(("%lu %hhu %d", c ? c->id : 0, pkt->tcp->flags, (int) pkt->pay.len));
 4829|       |#endif
 4830|     14|  if (c != NULL && c->is_connecting && pkt->tcp->flags == (TH_SYN | TH_ACK)) {
  ------------------
  |  | 4178|      0|#define TH_SYN 0x02
  ------------------
                if (c != NULL && c->is_connecting && pkt->tcp->flags == (TH_SYN | TH_ACK)) {
  ------------------
  |  | 4181|      0|#define TH_ACK 0x10
  ------------------
  |  Branch (4830:7): [True: 0, False: 14]
  |  Branch (4830:20): [True: 0, False: 0]
  |  Branch (4830:40): [True: 0, False: 0]
  ------------------
 4831|      0|    s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq) + 1;
 4832|      0|    tx_tcp_pkt(ifp, pkt, TH_ACK, pkt->tcp->ack, NULL, 0);
  ------------------
  |  | 4181|      0|#define TH_ACK 0x10
  ------------------
 4833|      0|    c->is_connecting = 0;  // Client connected
 4834|      0|    settmout(c, MIP_TTYPE_KEEPALIVE);
  ------------------
  |  | 4104|      0|#define MIP_TTYPE_KEEPALIVE 0  // Connection is idle for long, send keepalive
  ------------------
 4835|      0|    mg_call(c, MG_EV_CONNECT, NULL);  // Let user know
 4836|      0|    if (c->is_tls_hs) mg_tls_handshake(c);
  ------------------
  |  Branch (4836:9): [True: 0, False: 0]
  ------------------
 4837|     14|  } else if (c != NULL && c->is_connecting && pkt->tcp->flags != TH_ACK) {
  ------------------
  |  | 4181|      0|#define TH_ACK 0x10
  ------------------
  |  Branch (4837:14): [True: 0, False: 14]
  |  Branch (4837:27): [True: 0, False: 0]
  |  Branch (4837:47): [True: 0, False: 0]
  ------------------
 4838|       |    // mg_hexdump(pkt->raw.buf, pkt->raw.len);
 4839|      0|    tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0);
  ------------------
  |  | 4179|      0|#define TH_RST 0x04
  ------------------
                  tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0);
  ------------------
  |  | 4181|      0|#define TH_ACK 0x10
  ------------------
 4840|     14|  } else if (c != NULL && pkt->tcp->flags & TH_RST) {
  ------------------
  |  | 4179|      0|#define TH_RST 0x04
  ------------------
  |  Branch (4840:14): [True: 0, False: 14]
  |  Branch (4840:27): [True: 0, False: 0]
  ------------------
 4841|      0|    mg_error(c, "peer RST");  // RFC-1122 4.2.2.13
 4842|     14|  } else if (c != NULL) {
  ------------------
  |  Branch (4842:14): [True: 0, False: 14]
  ------------------
 4843|       |#if 0
 4844|       |    MG_DEBUG(("%lu %d %M:%hu -> %M:%hu", c->id, (int) pkt->raw.len,
 4845|       |              mg_print_ip4, &pkt->ip->src, mg_ntohs(pkt->tcp->sport),
 4846|       |              mg_print_ip4, &pkt->ip->dst, mg_ntohs(pkt->tcp->dport)));
 4847|       |    mg_hexdump(pkt->pay.buf, pkt->pay.len);
 4848|       |#endif
 4849|      0|    s->tmiss = 0;                         // Reset missed keep-alive counter
 4850|      0|    if (s->ttype == MIP_TTYPE_KEEPALIVE)  // Advance keep-alive timer
  ------------------
  |  | 4104|      0|#define MIP_TTYPE_KEEPALIVE 0  // Connection is idle for long, send keepalive
  ------------------
  |  Branch (4850:9): [True: 0, False: 0]
  ------------------
 4851|      0|      settmout(c,
 4852|      0|               MIP_TTYPE_KEEPALIVE);  // unless a former ACK timeout is pending
  ------------------
  |  | 4104|      0|#define MIP_TTYPE_KEEPALIVE 0  // Connection is idle for long, send keepalive
  ------------------
 4853|      0|    read_conn(c, pkt);  // Override timer with ACK timeout if needed
 4854|     14|  } else if ((c = getpeer(ifp->mgr, pkt, true)) == NULL) {
  ------------------
  |  Branch (4854:14): [True: 14, False: 0]
  ------------------
 4855|     14|    tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0);
  ------------------
  |  | 4179|     14|#define TH_RST 0x04
  ------------------
                  tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0);
  ------------------
  |  | 4181|     14|#define TH_ACK 0x10
  ------------------
 4856|     14|  } else if (pkt->tcp->flags & TH_RST) {
  ------------------
  |  | 4179|      0|#define TH_RST 0x04
  ------------------
  |  Branch (4856:14): [True: 0, False: 0]
  ------------------
 4857|      0|    if (c->is_accepted) mg_error(c, "peer RST");  // RFC-1122 4.2.2.13
  ------------------
  |  Branch (4857:9): [True: 0, False: 0]
  ------------------
 4858|       |    // ignore RST if not connected
 4859|      0|  } else if (pkt->tcp->flags & TH_SYN) {
  ------------------
  |  | 4178|      0|#define TH_SYN 0x02
  ------------------
  |  Branch (4859:14): [True: 0, False: 0]
  ------------------
 4860|       |    // Use peer's source port as ISN, in order to recognise the handshake
 4861|      0|    uint32_t isn = mg_htonl((uint32_t) mg_ntohs(pkt->tcp->sport));
  ------------------
  |  | 1114|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
 4862|      0|    tx_tcp_pkt(ifp, pkt, TH_SYN | TH_ACK, isn, NULL, 0);
  ------------------
  |  | 4178|      0|#define TH_SYN 0x02
  ------------------
                  tx_tcp_pkt(ifp, pkt, TH_SYN | TH_ACK, isn, NULL, 0);
  ------------------
  |  | 4181|      0|#define TH_ACK 0x10
  ------------------
 4863|      0|  } else if (pkt->tcp->flags & TH_FIN) {
  ------------------
  |  | 4177|      0|#define TH_FIN 0x01
  ------------------
  |  Branch (4863:14): [True: 0, False: 0]
  ------------------
 4864|      0|    tx_tcp_pkt(ifp, pkt, TH_FIN | TH_ACK, pkt->tcp->ack, NULL, 0);
  ------------------
  |  | 4177|      0|#define TH_FIN 0x01
  ------------------
                  tx_tcp_pkt(ifp, pkt, TH_FIN | TH_ACK, pkt->tcp->ack, NULL, 0);
  ------------------
  |  | 4181|      0|#define TH_ACK 0x10
  ------------------
 4865|      0|  } else if (mg_htonl(pkt->tcp->ack) == mg_htons(pkt->tcp->sport) + 1U) {
  ------------------
  |  | 1114|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
                } else if (mg_htonl(pkt->tcp->ack) == mg_htons(pkt->tcp->sport) + 1U) {
  ------------------
  |  | 1113|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (4865:14): [True: 0, False: 0]
  ------------------
 4866|      0|    accept_conn(c, pkt);
 4867|      0|  } else if (!c->is_accepted) {  // no peer
  ------------------
  |  Branch (4867:14): [True: 0, False: 0]
  ------------------
 4868|      0|    tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0);
  ------------------
  |  | 4179|      0|#define TH_RST 0x04
  ------------------
                  tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0);
  ------------------
  |  | 4181|      0|#define TH_ACK 0x10
  ------------------
 4869|      0|  } else {
 4870|       |    // MG_VERBOSE(("dropped silently.."));
 4871|      0|  }
 4872|     14|}
fuzz.c:_ZL10tx_tcp_pktP11mg_tcpip_ifP3pkthjPKvm:
 4642|     14|                         size_t len) {
 4643|     14|  uint32_t delta = (pkt->tcp->flags & (TH_SYN | TH_FIN)) ? 1 : 0;
  ------------------
  |  | 4178|     14|#define TH_SYN 0x02
  ------------------
                uint32_t delta = (pkt->tcp->flags & (TH_SYN | TH_FIN)) ? 1 : 0;
  ------------------
  |  | 4177|     14|#define TH_FIN 0x01
  ------------------
  |  Branch (4643:20): [True: 5, False: 9]
  ------------------
 4644|     14|  return tx_tcp(ifp, pkt->eth->src, pkt->ip->src, flags, pkt->tcp->dport,
 4645|     14|                pkt->tcp->sport, seq, mg_htonl(mg_ntohl(pkt->tcp->seq) + delta),
  ------------------
  |  | 1114|     14|#define mg_htonl(x) mg_ntohl(x)
  ------------------
 4646|     14|                buf, len);
 4647|     14|}

