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

LLVMFuzzerTestOneInput:
   72|  5.57k|int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   73|  5.57k|  mg_log_set(MG_LL_INFO);
  ------------------
  |  | 1778|  5.57k|#define mg_log_set(level_) mg_log_level = (level_)
  ------------------
   74|       |
   75|  5.57k|  struct mg_dns_message dm;
   76|  5.57k|  mg_dns_parse(data, size, &dm);
   77|  5.57k|  mg_dns_parse(NULL, 0, &dm);
   78|       |
   79|  5.57k|  struct mg_http_message hm;
   80|  5.57k|  if (mg_http_parse((const char *) data, size, &hm) > 0) {
  ------------------
  |  Branch (80:7): [True: 2.04k, False: 3.53k]
  ------------------
   81|  2.04k|    mg_crc32(0, hm.method.buf, hm.method.len);
   82|  2.04k|    mg_crc32(0, hm.uri.buf, hm.uri.len);
   83|  2.04k|    mg_crc32(0, hm.uri.buf, hm.uri.len);
   84|  63.3k|    for (size_t i = 0; i < sizeof(hm.headers) / sizeof(hm.headers[0]); i++) {
  ------------------
  |  Branch (84:24): [True: 61.2k, False: 2.04k]
  ------------------
   85|  61.2k|      struct mg_str *k = &hm.headers[i].name, *v = &hm.headers[i].value;
   86|  61.2k|      mg_crc32(0, k->buf, k->len);
   87|  61.2k|      mg_crc32(0, v->buf, v->len);
   88|  61.2k|    }
   89|  2.04k|  }
   90|  5.57k|  mg_http_parse(NULL, 0, &hm);
   91|       |
   92|  5.57k|  struct mg_str body = mg_str_n((const char *) data, size);
   93|  5.57k|  char tmp[256];
   94|  5.57k|  mg_http_get_var(&body, "key", tmp, sizeof(tmp));
   95|  5.57k|  mg_http_get_var(&body, "key", NULL, 0);
   96|  5.57k|  mg_url_decode((char *) data, size, tmp, sizeof(tmp), 1);
   97|  5.57k|  mg_url_decode((char *) data, size, tmp, 1, 1);
   98|  5.57k|  mg_url_decode(NULL, 0, tmp, 1, 1);
   99|       |
  100|  5.57k|  struct mg_mqtt_message mm;
  101|  5.57k|  if (mg_mqtt_parse(data, size, 0, &mm) == MQTT_OK) {
  ------------------
  |  Branch (101:7): [True: 2.24k, False: 3.33k]
  ------------------
  102|  2.24k|    mg_crc32(0, mm.topic.buf, mm.topic.len);
  103|  2.24k|    mg_crc32(0, mm.data.buf, mm.data.len);
  104|  2.24k|    mg_crc32(0, mm.dgram.buf, mm.dgram.len);
  105|  2.24k|  }
  106|  5.57k|  mg_mqtt_parse(NULL, 0, 0, &mm);
  107|  5.57k|  if (mg_mqtt_parse(data, size, 5, &mm) == MQTT_OK) {
  ------------------
  |  Branch (107:7): [True: 2.10k, False: 3.47k]
  ------------------
  108|  2.10k|    mg_crc32(0, mm.topic.buf, mm.topic.len);
  109|  2.10k|    mg_crc32(0, mm.data.buf, mm.data.len);
  110|  2.10k|    mg_crc32(0, mm.dgram.buf, mm.dgram.len);
  111|  2.10k|    {
  112|  2.10k|      struct mg_mqtt_prop prop;
  113|  2.10k|      size_t ofs = 0;
  114|  7.47k|      while ((ofs = mg_mqtt_next_prop(&mm, &prop, ofs)) > 0) {
  ------------------
  |  Branch (114:14): [True: 5.37k, False: 2.10k]
  ------------------
  115|  5.37k|          mg_crc32(0, prop.key.buf, prop.key.len);
  116|  5.37k|          mg_crc32(0, prop.val.buf, prop.val.len);
  117|  5.37k|      }
  118|  2.10k|    }
  119|  2.10k|  }
  120|  5.57k|  mg_mqtt_parse(NULL, 0, 5, &mm);
  121|       |
  122|  5.57k|  mg_sntp_parse(data, size);
  123|  5.57k|  mg_sntp_parse(NULL, 0);
  124|       |
  125|  5.57k|  char buf[size * 4 / 3 + 5];  // At least 4 chars and nul termination
  126|  5.57k|  mg_base64_decode((char *) data, size, buf, sizeof(buf));
  127|  5.57k|  mg_base64_decode(NULL, 0, buf, sizeof(buf));
  128|  5.57k|  mg_base64_encode(data, size, buf, sizeof(buf));
  129|  5.57k|  mg_base64_encode(NULL, 0, buf, sizeof(buf));
  130|       |
  131|  5.57k|  mg_match(mg_str_n((char *) data, size), mg_str_n((char *) data, size), NULL);
  132|       |
  133|  5.57k|  struct mg_str entry, s = mg_str_n((char *) data, size);
  134|  1.08M|  while (mg_span(s, &entry, &s, ',')) entry.len = 0;
  ------------------
  |  Branch (134:10): [True: 1.07M, False: 5.57k]
  ------------------
  135|       |
  136|  5.57k|  int n;
  137|  5.57k|  mg_json_get(mg_str_n((char *) data, size), "$", &n);
  138|  5.57k|  mg_json_get(mg_str_n((char *) data, size), "$.a.b", &n);
  139|  5.57k|  mg_json_get(mg_str_n((char *) data, size), "$[0]", &n);
  140|       |
  141|       |  // Test built-in TCP/IP stack
  142|  5.57k|  if (size > 0) {
  ------------------
  |  Branch (142:7): [True: 5.57k, False: 0]
  ------------------
  143|  5.57k|    static size_t t;
  144|  5.57k|    struct mg_tcpip_if mif = {.ip = 1,
  145|  5.57k|                              .mask = 255,
  146|  5.57k|                              .gw = 1,
  147|  5.57k|                              .gw_ready = true,
  148|  5.57k|                              .state = MG_TCPIP_STATE_READY,
  ------------------
  |  | 4740|  5.57k|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
  149|       |#if MG_ENABLE_IPV6
  150|       |                              .ip6[0] = 1,
  151|       |                              .prefix[0] = 1,
  152|       |                              .prefix_len = 64,
  153|       |                              .gw6[0] = 1,
  154|       |                              .gw6_ready = true,
  155|       |                              .state6 = MG_TCPIP_STATE_READY,  // so mg_send() works and RS stops
  156|       |#endif
  157|  5.57k|                              .driver = &mg_tcpip_driver_mock};
  158|  5.57k|    struct mg_mgr mgr;
  159|       |
  160|  5.57k|    if (t >= MG_TCPIP_L2_USER) t = 0; // defined in l2.h
  ------------------
  |  Branch (160:9): [True: 1.85k, False: 3.71k]
  ------------------
  161|  5.57k|    mif.l2type = (enum mg_l2type) t++; // configure to a L2 type
  162|       |
  163|  5.57k|    mg_mgr_init(&mgr);
  164|  5.57k|    mg_tcpip_init(&mgr, &mif);
  165|       |
  166|       |    // Make a copy of the random data, in order to modify it
  167|  5.57k|    void *pkt = malloc(size);
  168|  5.57k|    struct eth *eth = (struct eth *) pkt;
  169|  5.57k|    memcpy(pkt, data, size);
  170|  5.57k|    if ((mif.l2type == MG_TCPIP_L2_ETH || mif.l2type == MG_TCPIP_L2_PPPoE) && size > sizeof(*eth)) {
  ------------------
  |  Branch (170:10): [True: 1.85k, False: 3.71k]
  |  Branch (170:43): [True: 1.85k, False: 1.85k]
  |  Branch (170:79): [True: 2.65k, False: 1.06k]
  ------------------
  171|  2.65k|      static size_t i, v;
  172|  2.65k|      static struct fuzz_l3_state l3;
  173|  2.65k|      uint8_t *ethpay = (uint8_t *) (eth + 1);
  174|  2.65k|      size_t ethhdrsz = sizeof(*eth);
  175|  2.65k|      uint16_t etype;
  176|       |      // eth_types[] exists in l2_eth.c
  177|  2.65k|      memcpy(eth->dst, mif.mac, 6);  // Set valid destination MAC
  178|       |      // send all handled eth types, then 2 random ones
  179|  2.65k|      if (i >= (sizeof(eth_types) / sizeof(eth_types[0]) + 2)) i = 0;
  ------------------
  |  Branch (179:11): [True: 0, False: 2.65k]
  ------------------
  180|  2.65k|      if (i < (sizeof(eth_types) / sizeof(eth_types[0]))) eth->type = mg_htons(eth_types[i++]);
  ------------------
  |  | 2094|      5|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (180:11): [True: 5, False: 2.64k]
  ------------------
  181|  2.65k|      etype = mg_ntohs(eth->type);
  182|  2.65k|      if (v >= 10) v = 0; // 802.1Q tag 3 out of 10 frames
  ------------------
  |  Branch (182:11): [True: 265, False: 2.38k]
  ------------------
  183|  2.65k|      if (v < 3) mif.l2data.eth.vlan_id = 123;
  ------------------
  |  Branch (183:11): [True: 798, False: 1.85k]
  ------------------
  184|  2.65k|      if (size > sizeof(*eth) + sizeof(struct qtag)) {
  ------------------
  |  Branch (184:11): [True: 2.41k, False: 240]
  ------------------
  185|  2.41k|        struct qtag *qtag = (struct qtag *) &eth->type;
  186|  2.41k|        if (v == 0) {
  ------------------
  |  Branch (186:13): [True: 242, False: 2.17k]
  ------------------
  187|       |          // v=0: configured for VLAN 123, untagged frame, discard path
  188|  2.17k|        } else if (v == 1) {
  ------------------
  |  Branch (188:20): [True: 242, False: 1.92k]
  ------------------
  189|       |          // v=1: configured for VLAN 123, tagged VLAN 123, accept path
  190|    242|          qtag->tpid = mg_htons(0x8100);
  ------------------
  |  | 2094|    242|#define mg_htons(x) mg_ntohs(x)
  ------------------
  191|    242|          qtag->tci = mg_htons(123);
  ------------------
  |  | 2094|    242|#define mg_htons(x) mg_ntohs(x)
  ------------------
  192|    242|          MG_STORE_BE16(qtag + 1, etype);
  ------------------
  |  | 2060|    242|  do {                                    \
  |  | 2061|    242|    MG_U8P(p)[0] = (uint8_t) ((n) >> 8U); \
  |  |  ------------------
  |  |  |  | 2033|    242|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2062|    242|    MG_U8P(p)[1] = (uint8_t) (n);         \
  |  |  ------------------
  |  |  |  | 2033|    242|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2063|    242|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2063:12): [Folded, False: 242]
  |  |  ------------------
  ------------------
  193|    242|          ethhdrsz += sizeof(*qtag);
  194|    242|          ethpay += sizeof(*qtag);
  195|  1.92k|        } else if (v == 2) {
  ------------------
  |  Branch (195:20): [True: 242, False: 1.68k]
  ------------------
  196|       |          // v=2: configured for VLAN 123, tagged random VLAN, mismatch path
  197|    242|          qtag->tpid = mg_htons(0x8100);
  ------------------
  |  | 2094|    242|#define mg_htons(x) mg_ntohs(x)
  ------------------
  198|    242|          MG_STORE_BE16(qtag + 1, etype);
  ------------------
  |  | 2060|    242|  do {                                    \
  |  | 2061|    242|    MG_U8P(p)[0] = (uint8_t) ((n) >> 8U); \
  |  |  ------------------
  |  |  |  | 2033|    242|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2062|    242|    MG_U8P(p)[1] = (uint8_t) (n);         \
  |  |  ------------------
  |  |  |  | 2033|    242|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2063|    242|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2063:12): [Folded, False: 242]
  |  |  ------------------
  ------------------
  199|    242|          ethhdrsz += sizeof(*qtag);
  200|    242|          ethpay += sizeof(*qtag);
  201|  1.68k|        } else if (v == 3) {
  ------------------
  |  Branch (201:20): [True: 241, False: 1.44k]
  ------------------
  202|       |          // v=3: unconfigured VLAN, tagged frame, discard path
  203|    241|          qtag->tpid = mg_htons(0x8100);
  ------------------
  |  | 2094|    241|#define mg_htons(x) mg_ntohs(x)
  ------------------
  204|    241|          MG_STORE_BE16(qtag + 1, etype);
  ------------------
  |  | 2060|    241|  do {                                    \
  |  | 2061|    241|    MG_U8P(p)[0] = (uint8_t) ((n) >> 8U); \
  |  |  ------------------
  |  |  |  | 2033|    241|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2062|    241|    MG_U8P(p)[1] = (uint8_t) (n);         \
  |  |  ------------------
  |  |  |  | 2033|    241|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2063|    241|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2063:12): [Folded, False: 241]
  |  |  ------------------
  ------------------
  205|    241|          ethhdrsz += sizeof(*qtag);
  206|    241|          ethpay += sizeof(*qtag);
  207|    241|        } // else unconfigured VLAN, untagged frame, normal path
  208|  2.41k|      }
  209|  2.65k|      ++v;
  210|  2.65k|      if (etype == 0x8863 && size > (ethhdrsz + sizeof(struct pppoe))) { // PPPoE disc
  ------------------
  |  Branch (210:11): [True: 62, False: 2.59k]
  |  Branch (210:30): [True: 58, False: 4]
  ------------------
  211|     58|        static size_t j;
  212|     58|        uint8_t pppoe_codes[] = {MG_PPPoE_PADO, MG_PPPoE_PADS, MG_PPPoE_PADT}; // defined in l2_ppp.c
  ------------------
  |  | 6083|     58|#define MG_PPPoE_PADO 0x07
  ------------------
                      uint8_t pppoe_codes[] = {MG_PPPoE_PADO, MG_PPPoE_PADS, MG_PPPoE_PADT}; // defined in l2_ppp.c
  ------------------
  |  | 6085|     58|#define MG_PPPoE_PADS 0x65
  ------------------
                      uint8_t pppoe_codes[] = {MG_PPPoE_PADO, MG_PPPoE_PADS, MG_PPPoE_PADT}; // defined in l2_ppp.c
  ------------------
  |  | 6086|     58|#define MG_PPPoE_PADT 0xa7
  ------------------
  213|     58|        struct pppoe *pppoe = (struct pppoe *) ethpay;
  214|     58|        pppoe->vertype = 0x11;
  215|       |        // send all handled PPPoE codes, then 2 random ones
  216|     58|        if (j >= (sizeof(pppoe_codes) / sizeof(pppoe_codes[0]) + 2)) j = 0;
  ------------------
  |  Branch (216:13): [True: 0, False: 58]
  ------------------
  217|     58|        if (j < (sizeof(pppoe_codes) / sizeof(pppoe_codes[0]))) pppoe->code = (pppoe_codes[j++]);
  ------------------
  |  Branch (217:13): [True: 3, False: 55]
  ------------------
  218|     58|        if (pppoe->code == MG_PPPoE_PADO) {
  ------------------
  |  | 6083|     58|#define MG_PPPoE_PADO 0x07
  ------------------
  |  Branch (218:13): [True: 4, False: 54]
  ------------------
  219|      4|          static size_t k;
  220|       |          // send id=0, then 2 random ids
  221|      4|          if (k >= 3) k = 0;
  ------------------
  |  Branch (221:15): [True: 1, False: 3]
  ------------------
  222|      4|          if (k == 0) pppoe->id = 0;
  ------------------
  |  Branch (222:15): [True: 2, False: 2]
  ------------------
  223|      4|          ++k;
  224|     54|        } else if (pppoe->code == MG_PPPoE_PADS) {
  ------------------
  |  | 6085|     54|#define MG_PPPoE_PADS 0x65
  ------------------
  |  Branch (224:20): [True: 7, False: 47]
  ------------------
  225|      7|          static size_t k;
  226|       |          // send id=x, then 2 random ids
  227|      7|          if (k >= 3) k = 0;
  ------------------
  |  Branch (227:15): [True: 2, False: 5]
  ------------------
  228|      7|          if (k == 0) pppoe->id = 0x1234;
  ------------------
  |  Branch (228:15): [True: 3, False: 4]
  ------------------
  229|      7|          ++k;
  230|     47|        } else if (pppoe->code == MG_PPPoE_PADT) { // keep separate so they do not correlate too much
  ------------------
  |  | 6086|     47|#define MG_PPPoE_PADT 0xa7
  ------------------
  |  Branch (230:20): [True: 10, False: 37]
  ------------------
  231|     10|          static size_t k;
  232|       |          // send id=x, then 2 random ids
  233|     10|          if (k >= 3) k = 0;
  ------------------
  |  Branch (233:15): [True: 3, False: 7]
  ------------------
  234|     10|          if (k == 0) pppoe->id = 0x1234;
  ------------------
  |  Branch (234:15): [True: 4, False: 6]
  ------------------
  235|     10|          ++k;
  236|     10|        }
  237|  2.59k|      } else if (etype == 0x8864 && size > (ethhdrsz + sizeof(struct pppoe))) { // PPPoE sess
  ------------------
  |  Branch (237:18): [True: 45, False: 2.55k]
  |  Branch (237:37): [True: 41, False: 4]
  ------------------
  238|       |        // PPP rx is covered via HDLC too; PPPoE tx wrapping may remain unexercised.
  239|     41|        struct pppoe *pppoe = (struct pppoe *) ethpay;
  240|     41|        static size_t k, l;
  241|       |        // send code=0, then 2 random codes
  242|     41|        if (k >= 3) k = 0;
  ------------------
  |  Branch (242:13): [True: 13, False: 28]
  ------------------
  243|     41|        if (k == 0)  {
  ------------------
  |  Branch (243:13): [True: 14, False: 27]
  ------------------
  244|     14|          static size_t m;
  245|     14|          pppoe->code = 0;
  246|       |          // send id=x, then 2 random ids
  247|     14|          if (m >= 3) m = 0;
  ------------------
  |  Branch (247:15): [True: 4, False: 10]
  ------------------
  248|     14|          if (m == 0) pppoe->id = 0x1234;
  ------------------
  |  Branch (248:15): [True: 5, False: 9]
  ------------------
  249|     14|          ++m;
  250|     14|        }
  251|     41|        ++k;
  252|       |        // set s_state to valid and invalid
  253|     41|        if (l >= 2) l = 0;
  ------------------
  |  Branch (253:13): [True: 20, False: 21]
  ------------------
  254|     41|        if (l == 0) s_state = MG_PPPoE_ST_SESS; // defined in l2_ppp.c
  ------------------
  |  | 6090|     21|#define MG_PPPoE_ST_SESS 2  // Session established, PPP traffic is exchanged
  ------------------
  |  Branch (254:13): [True: 21, False: 20]
  ------------------
  255|     41|        if (l == 1) s_state = MG_PPPoE_ST_REQ;
  ------------------
  |  | 6089|     20|#define MG_PPPoE_ST_REQ 1   // Chose a server, request a session and wait
  ------------------
  |  Branch (255:13): [True: 20, False: 21]
  ------------------
  256|     41|        ++l;
  257|       |        // PPP exercised in other block
  258|     41|      }
  259|       |      // build proper layer-3 datagrams, to be able to exercise layers above
  260|  2.55k|      else if (etype == 0x800 && size > (ethhdrsz + sizeof(struct ip))) {         // IPv4
  ------------------
  |  Branch (260:16): [True: 119, False: 2.43k]
  |  Branch (260:34): [True: 109, False: 10]
  ------------------
  261|    109|        fuzz_ip4(ethpay, size - ethhdrsz, &l3);
  262|  2.44k|      } else if (etype == 0x806) {      // ARP
  ------------------
  |  Branch (262:18): [True: 50, False: 2.39k]
  ------------------
  263|       |
  264|  2.39k|      } else if (etype == 0x86dd && size > (ethhdrsz + sizeof(struct ip6))) {     // IPv6
  ------------------
  |  Branch (264:18): [True: 23, False: 2.37k]
  |  Branch (264:37): [True: 21, False: 2]
  ------------------
  265|     21|        fuzz_ip6(ethpay, size - ethhdrsz, &l3);
  266|     21|      }
  267|  2.92k|    } else if (mif.l2type == MG_TCPIP_L2_PPP && size > (sizeof(struct hdlc_) + sizeof(struct ppp) + 2)) {
  ------------------
  |  Branch (267:16): [True: 1.85k, False: 1.06k]
  |  Branch (267:49): [True: 1.56k, False: 290]
  ------------------
  268|  1.56k|      static size_t i;
  269|  1.56k|      static struct fuzz_l3_state l3;
  270|  1.56k|      uint16_t ppp_protos[] = {
  271|  1.56k|          MG_PPP_PROTO_LCP, MG_PPP_PROTO_IPCP, MG_PPP_PROTO_IP, MG_PPP_PROTO_IPV6CP, MG_PPP_PROTO_IPV6
  ------------------
  |  | 6054|  1.56k|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
                        MG_PPP_PROTO_LCP, MG_PPP_PROTO_IPCP, MG_PPP_PROTO_IP, MG_PPP_PROTO_IPV6CP, MG_PPP_PROTO_IPV6
  ------------------
  |  | 6055|  1.56k|#define MG_PPP_PROTO_IPCP 0x8021
  ------------------
                        MG_PPP_PROTO_LCP, MG_PPP_PROTO_IPCP, MG_PPP_PROTO_IP, MG_PPP_PROTO_IPV6CP, MG_PPP_PROTO_IPV6
  ------------------
  |  | 6052|  1.56k|#define MG_PPP_PROTO_IP 0x0021
  ------------------
                        MG_PPP_PROTO_LCP, MG_PPP_PROTO_IPCP, MG_PPP_PROTO_IP, MG_PPP_PROTO_IPV6CP, MG_PPP_PROTO_IPV6
  ------------------
  |  | 6056|  1.56k|#define MG_PPP_PROTO_IPV6CP 0x8057
  ------------------
                        MG_PPP_PROTO_LCP, MG_PPP_PROTO_IPCP, MG_PPP_PROTO_IP, MG_PPP_PROTO_IPV6CP, MG_PPP_PROTO_IPV6
  ------------------
  |  | 6053|  1.56k|#define MG_PPP_PROTO_IPV6 0x0057
  ------------------
  272|  1.56k|      };
  273|  1.56k|      struct hdlc_ *hdlc = (struct hdlc_ *) pkt;
  274|  1.56k|      struct ppp *ppp = (struct ppp *) (hdlc + 1);
  275|  1.56k|      size_t len = size - sizeof(*hdlc) - sizeof(*ppp) - 2;
  276|  1.56k|      hdlc->addr = MG_PPP_ADDR;
  ------------------
  |  | 6049|  1.56k|#define MG_PPP_ADDR 0xff
  ------------------
  277|  1.56k|      hdlc->ctrl = MG_PPP_CTRL;
  ------------------
  |  | 6050|  1.56k|#define MG_PPP_CTRL 0x03
  ------------------
  278|  1.56k|      s_lcpup = true;
  279|       |      // send all handled PPP protocols, then 2 random ones
  280|  1.56k|      if (i >= (sizeof(ppp_protos) / sizeof(ppp_protos[0]) + 2)) i = 0;
  ------------------
  |  Branch (280:11): [True: 0, False: 1.56k]
  ------------------
  281|  1.56k|      if (i < (sizeof(ppp_protos) / sizeof(ppp_protos[0]))) ppp->proto = mg_htons(ppp_protos[i++]);
  ------------------
  |  | 2094|      5|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (281:11): [True: 5, False: 1.56k]
  ------------------
  282|  1.56k|      if (ppp->proto == mg_htons(MG_PPP_PROTO_LCP) && len >= sizeof(struct lcp)) {
  ------------------
  |  | 2094|  3.13k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (282:11): [True: 41, False: 1.52k]
  |  Branch (282:55): [True: 40, False: 1]
  ------------------
  283|     40|        static size_t j, k;
  284|     40|        uint8_t lcp_codes[] = {MG_PPP_LCP_CFG_REQ, MG_PPP_LCP_CFG_ACK, MG_PPP_LCP_CFG_TERM_REQ, MG_PPP_LCP_ECHO_REQ};
  ------------------
  |  | 6060|     40|#define MG_PPP_LCP_CFG_REQ 1
  ------------------
                      uint8_t lcp_codes[] = {MG_PPP_LCP_CFG_REQ, MG_PPP_LCP_CFG_ACK, MG_PPP_LCP_CFG_TERM_REQ, MG_PPP_LCP_ECHO_REQ};
  ------------------
  |  | 6061|     40|#define MG_PPP_LCP_CFG_ACK 2
  ------------------
                      uint8_t lcp_codes[] = {MG_PPP_LCP_CFG_REQ, MG_PPP_LCP_CFG_ACK, MG_PPP_LCP_CFG_TERM_REQ, MG_PPP_LCP_ECHO_REQ};
  ------------------
  |  | 6064|     40|#define MG_PPP_LCP_CFG_TERM_REQ 5
  ------------------
                      uint8_t lcp_codes[] = {MG_PPP_LCP_CFG_REQ, MG_PPP_LCP_CFG_ACK, MG_PPP_LCP_CFG_TERM_REQ, MG_PPP_LCP_ECHO_REQ};
  ------------------
  |  | 6067|     40|#define MG_PPP_LCP_ECHO_REQ 9
  ------------------
  285|     40|        struct lcp *lcp = (struct lcp *) (ppp + 1);
  286|       |        // send all handled LCP codes, then 2 random ones
  287|     40|        if (j >= (sizeof(lcp_codes) / sizeof(lcp_codes[0]) + 2)) j = 0;
  ------------------
  |  Branch (287:13): [True: 0, False: 40]
  ------------------
  288|     40|        if (j < (sizeof(lcp_codes) / sizeof(lcp_codes[0]))) lcp->code = lcp_codes[j++];
  ------------------
  |  Branch (288:13): [True: 4, False: 36]
  ------------------
  289|       |        // send valid length, then 2 random lengths
  290|     40|        if (k >= 3) k = 0;
  ------------------
  |  Branch (290:13): [True: 13, False: 27]
  ------------------
  291|     40|        if (k == 0) lcp->len = mg_htons((uint16_t) sizeof(*lcp));
  ------------------
  |  | 2094|     14|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (291:13): [True: 14, False: 26]
  ------------------
  292|     40|        ++k;
  293|  1.52k|      } else if (ppp->proto == mg_htons(MG_PPP_PROTO_IPCP) && len >= 10) {
  ------------------
  |  | 2094|  3.05k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (293:18): [True: 36, False: 1.49k]
  |  Branch (293:63): [True: 27, False: 9]
  ------------------
  294|     27|        static size_t j, k, m;
  295|     27|        uint8_t ipcp_codes[] = {MG_PPP_IPCP_CFG_REQ, MG_PPP_IPCP_CFG_ACK, MG_PPP_IPCP_CFG_NACK, MG_PPP_IPCP_CFG_REJECT};
  ------------------
  |  | 6070|     27|#define MG_PPP_IPCP_CFG_REQ 1
  ------------------
                      uint8_t ipcp_codes[] = {MG_PPP_IPCP_CFG_REQ, MG_PPP_IPCP_CFG_ACK, MG_PPP_IPCP_CFG_NACK, MG_PPP_IPCP_CFG_REJECT};
  ------------------
  |  | 6071|     27|#define MG_PPP_IPCP_CFG_ACK 2
  ------------------
                      uint8_t ipcp_codes[] = {MG_PPP_IPCP_CFG_REQ, MG_PPP_IPCP_CFG_ACK, MG_PPP_IPCP_CFG_NACK, MG_PPP_IPCP_CFG_REJECT};
  ------------------
  |  | 6072|     27|#define MG_PPP_IPCP_CFG_NACK 3
  ------------------
                      uint8_t ipcp_codes[] = {MG_PPP_IPCP_CFG_REQ, MG_PPP_IPCP_CFG_ACK, MG_PPP_IPCP_CFG_NACK, MG_PPP_IPCP_CFG_REJECT};
  ------------------
  |  | 6073|     27|#define MG_PPP_IPCP_CFG_REJECT 4
  ------------------
  296|     27|        struct ipcp *ipcp = (struct ipcp *) (ppp + 1);
  297|     27|        uint8_t *opts = (uint8_t *) (ipcp + 1);
  298|       |        // send all handled IPCP codes, then 2 random ones
  299|     27|        if (j >= (sizeof(ipcp_codes) / sizeof(ipcp_codes[0]) + 2)) j = 0;
  ------------------
  |  Branch (299:13): [True: 0, False: 27]
  ------------------
  300|     27|        if (j < (sizeof(ipcp_codes) / sizeof(ipcp_codes[0]))) ipcp->code = ipcp_codes[j++];
  ------------------
  |  Branch (300:13): [True: 4, False: 23]
  ------------------
  301|       |        // send valid length, then 2 random lengths
  302|     27|        if (m >= 3) m = 0;
  ------------------
  |  Branch (302:13): [True: 8, False: 19]
  ------------------
  303|     27|        if (m == 0) ipcp->len = mg_htons(10);
  ------------------
  |  | 2094|      9|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (303:13): [True: 9, False: 18]
  ------------------
  304|     27|        ++m;
  305|       |        // send valid IPADDR option, then 2 random option types
  306|     27|        if (k >= 3) k = 0;
  ------------------
  |  Branch (306:13): [True: 8, False: 19]
  ------------------
  307|     27|        if (k == 0) {
  ------------------
  |  Branch (307:13): [True: 9, False: 18]
  ------------------
  308|      9|          static size_t l;
  309|      9|          opts[0] = MG_PPP_IPCP_OPT_IPADDR;
  ------------------
  |  | 6074|      9|#define MG_PPP_IPCP_OPT_IPADDR 3
  ------------------
  310|       |          // for valid option type, send valid length, then random length
  311|      9|          if (l >= 2) l = 0;
  ------------------
  |  Branch (311:15): [True: 4, False: 5]
  ------------------
  312|      9|          if (l == 0) opts[1] = 6;
  ------------------
  |  Branch (312:15): [True: 5, False: 4]
  ------------------
  313|      9|          ++l;
  314|      9|        }
  315|     27|        ++k;
  316|  1.50k|      } else if (ppp->proto == mg_htons(MG_PPP_PROTO_IP) && len >= sizeof(struct ip)) {
  ------------------
  |  | 2094|  3.00k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (316:18): [True: 33, False: 1.46k]
  |  Branch (316:61): [True: 31, False: 2]
  ------------------
  317|     31|        fuzz_ip4(ppp + 1, len, &l3);
  318|  1.47k|      } else if (ppp->proto == mg_htons(MG_PPP_PROTO_IPV6CP) && len >= 14) {
  ------------------
  |  | 2094|  2.94k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (318:18): [True: 21, False: 1.45k]
  |  Branch (318:65): [True: 19, False: 2]
  ------------------
  319|     19|        static size_t j, k, m;
  320|     19|        uint8_t ipv6cp_codes[] = {MG_PPP_IPV6CP_CFG_REQ, MG_PPP_IPV6CP_CFG_ACK, MG_PPP_IPV6CP_CFG_NACK, MG_PPP_IPV6CP_CFG_REJECT};
  ------------------
  |  | 6076|     19|#define MG_PPP_IPV6CP_CFG_REQ 1
  ------------------
                      uint8_t ipv6cp_codes[] = {MG_PPP_IPV6CP_CFG_REQ, MG_PPP_IPV6CP_CFG_ACK, MG_PPP_IPV6CP_CFG_NACK, MG_PPP_IPV6CP_CFG_REJECT};
  ------------------
  |  | 6077|     19|#define MG_PPP_IPV6CP_CFG_ACK 2
  ------------------
                      uint8_t ipv6cp_codes[] = {MG_PPP_IPV6CP_CFG_REQ, MG_PPP_IPV6CP_CFG_ACK, MG_PPP_IPV6CP_CFG_NACK, MG_PPP_IPV6CP_CFG_REJECT};
  ------------------
  |  | 6078|     19|#define MG_PPP_IPV6CP_CFG_NACK 3
  ------------------
                      uint8_t ipv6cp_codes[] = {MG_PPP_IPV6CP_CFG_REQ, MG_PPP_IPV6CP_CFG_ACK, MG_PPP_IPV6CP_CFG_NACK, MG_PPP_IPV6CP_CFG_REJECT};
  ------------------
  |  | 6079|     19|#define MG_PPP_IPV6CP_CFG_REJECT 4
  ------------------
  321|     19|        struct ipv6cp *ipv6cp = (struct ipv6cp *) (ppp + 1);
  322|     19|        uint8_t *opts = (uint8_t *) (ipv6cp + 1);
  323|       |        // send all handled IPV6CP codes, then 2 random ones
  324|     19|        if (j >= (sizeof(ipv6cp_codes) / sizeof(ipv6cp_codes[0]) + 2)) j = 0;
  ------------------
  |  Branch (324:13): [True: 0, False: 19]
  ------------------
  325|     19|        if (j < (sizeof(ipv6cp_codes) / sizeof(ipv6cp_codes[0]))) ipv6cp->code = ipv6cp_codes[j++];
  ------------------
  |  Branch (325:13): [True: 4, False: 15]
  ------------------
  326|       |        // send valid length, then 2 random lengths
  327|     19|        if (m >= 3) m = 0;
  ------------------
  |  Branch (327:13): [True: 6, False: 13]
  ------------------
  328|     19|        if (m == 0) ipv6cp->len = mg_htons(14);
  ------------------
  |  | 2094|      7|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (328:13): [True: 7, False: 12]
  ------------------
  329|     19|        ++m;
  330|       |        // send valid IFCID option, then 2 random option types
  331|     19|        if (k >= 3) k = 0;
  ------------------
  |  Branch (331:13): [True: 6, False: 13]
  ------------------
  332|     19|        if (k == 0) {
  ------------------
  |  Branch (332:13): [True: 7, False: 12]
  ------------------
  333|      7|          static size_t l;
  334|      7|          opts[0] = MG_PPP_IPV6CP_OPT_IFCID;
  ------------------
  |  | 6080|      7|#define MG_PPP_IPV6CP_OPT_IFCID 1
  ------------------
  335|       |          // for valid option type, send valid length, then random length
  336|      7|          if (l >= 2) l = 0;
  ------------------
  |  Branch (336:15): [True: 3, False: 4]
  ------------------
  337|      7|          if (l == 0) {
  ------------------
  |  Branch (337:15): [True: 4, False: 3]
  ------------------
  338|      4|            static size_t o;
  339|      4|            opts[1] = 10;
  340|       |            // for valid option length, send non-zero IFCID, then 2 random IFCIDs
  341|      4|            if (o >= 3) o = 0;
  ------------------
  |  Branch (341:17): [True: 1, False: 3]
  ------------------
  342|      4|            if (o == 0) opts[9] = 1;
  ------------------
  |  Branch (342:17): [True: 2, False: 2]
  ------------------
  343|      4|            ++o;
  344|      4|          }
  345|      7|          ++l;
  346|      7|        }
  347|     19|        ++k;
  348|  1.45k|      } else if (ppp->proto == mg_htons(MG_PPP_PROTO_IPV6) && len >= sizeof(struct ip6)) {
  ------------------
  |  | 2094|  2.90k|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (348:18): [True: 51, False: 1.40k]
  |  Branch (348:63): [True: 46, False: 5]
  ------------------
  349|     46|        fuzz_ip6(ppp + 1, len, &l3);
  350|     46|      }
  351|  1.56k|    }
  352|       |
  353|       |#if defined(MAIN)
  354|       |    printf("Sending to net_builtin:\n");
  355|       |    mg_hexdump(pkt, size);
  356|       |#endif
  357|  5.57k|    mg_tcpip_rx(&mif, pkt, size);
  358|       |
  359|       |    // prior actions may have had consequences on link state
  360|  5.57k|    mif.state = MG_TCPIP_STATE_READY;
  ------------------
  |  | 4740|  5.57k|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
  361|       |    // Test HTTP serving (via our built-in TCP/IP stack)
  362|  5.57k|    const char *url = "http://localhost:12345"; // internally resolves
  363|       |    // creates a connection and sends SYN via the router, unless OOM
  364|  5.57k|    struct mg_connection *c = mg_http_connect(&mgr, url, fn, NULL);
  365|  5.57k|    mg_iobuf_add(&c->recv, 0, data, size);
  366|  5.57k|    c->pfn(c, MG_EV_READ, NULL); // manually invoke protocol event handler
  367|       |
  368|  5.57k|    free(pkt);
  369|  5.57k|    mg_mgr_free(&mgr);
  370|  5.57k|  }
  371|       |
  372|  5.57k|  return 0;
  373|  5.57k|}
fuzz.c:_ZL8fuzz_ip4PvmP13fuzz_l3_state:
   32|    140|static void fuzz_ip4(void *buf, size_t len, struct fuzz_l3_state *st) {
   33|    140|  if (len >= sizeof(struct ip)) {
  ------------------
  |  Branch (33:7): [True: 140, False: 0]
  ------------------
   34|    140|    uint8_t ip_protos[] = {1, 6, 17}; // ICMP, TCP, UDP
   35|    140|    struct ip *ip4 = (struct ip *) buf;
   36|    140|    ip4->ver = (uint8_t) ((ip4->ver & ~0xf0) | (4 << 4));
   37|       |    // send all handled IP protos, then 2 random ones
   38|    140|    if (st->ip_proto >= (sizeof(ip_protos) / sizeof(ip_protos[0]) + 2)) st->ip_proto = 0;
  ------------------
  |  Branch (38:9): [True: 0, False: 140]
  ------------------
   39|    140|    if (st->ip_proto < (sizeof(ip_protos) / sizeof(ip_protos[0]))) ip4->proto = ip_protos[st->ip_proto++];
  ------------------
  |  Branch (39:9): [True: 6, False: 134]
  ------------------
   40|    140|    if (ip4->proto == 1) { // ICMP
  ------------------
  |  Branch (40:9): [True: 22, False: 118]
  ------------------
   41|    118|    } else if (ip4->proto == 6) { // TCP
  ------------------
  |  Branch (41:16): [True: 2, False: 116]
  ------------------
   42|    116|    } else if (ip4->proto == 17 && len >= sizeof(struct ip) + sizeof(struct udp)) { // UDP
  ------------------
  |  Branch (42:16): [True: 24, False: 92]
  |  Branch (42:36): [True: 20, False: 4]
  ------------------
   43|     20|      uint16_t udp_ports[] = {67, 68}; // DHCP server and client
   44|     20|      struct udp *udp = (struct udp *) (ip4 + 1);
   45|       |      // send all handled UDP ports, then 2 random ones
   46|     20|      if (st->udp_port >= (sizeof(udp_ports) / sizeof(udp_ports[0]) + 2)) st->udp_port = 0;
  ------------------
  |  Branch (46:11): [True: 0, False: 20]
  ------------------
   47|     20|      if (st->udp_port < (sizeof(udp_ports) / sizeof(udp_ports[0]))) udp->dport = mg_htons(udp_ports[st->udp_port++]);
  ------------------
  |  | 2094|      2|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (47:11): [True: 2, False: 18]
  ------------------
   48|     20|    }
   49|    140|  }
   50|    140|}
fuzz.c:_ZL8fuzz_ip6PvmP13fuzz_l3_state:
   52|     67|static void fuzz_ip6(void *buf, size_t len, struct fuzz_l3_state *st) {
   53|     67|  if (len >= sizeof(struct ip6)) {
  ------------------
  |  Branch (53:7): [True: 67, False: 0]
  ------------------
   54|     67|    uint8_t ip6_protos[] = {6, 17, 58}; // TCP, UDP, ICMPv6
   55|     67|    struct ip6 *ip6 = (struct ip6 *) buf;
   56|     67|    ip6->ver = (uint8_t) ((ip6->ver & ~0xf0) | (6 << 4));
   57|       |    // send all handled IPv6 "next headers", then 2 random ones
   58|     67|    if (st->ip6_next >= (sizeof(ip6_protos) / sizeof(ip6_protos[0]) + 2)) st->ip6_next = 0;
  ------------------
  |  Branch (58:9): [True: 0, False: 67]
  ------------------
   59|     67|    if (st->ip6_next < (sizeof(ip6_protos) / sizeof(ip6_protos[0]))) ip6->next = ip6_protos[st->ip6_next++];
  ------------------
  |  Branch (59:9): [True: 6, False: 61]
  ------------------
   60|     67|    if (ip6->next == 6) { // TCP
  ------------------
  |  Branch (60:9): [True: 2, False: 65]
  ------------------
   61|     65|    } else if (ip6->next == 17) { // UDP
  ------------------
  |  Branch (61:16): [True: 2, False: 63]
  ------------------
   62|     63|    } else if (ip6->next == 58 && len >= sizeof(struct ip6) + sizeof(struct icmp6)) { // ICMPv6
  ------------------
  |  Branch (62:16): [True: 26, False: 37]
  |  Branch (62:35): [True: 25, False: 1]
  ------------------
   63|     25|      uint8_t icmp6_types[] = {128, 134, 135, 136}; // Echo Request, RA, NS, NA
   64|     25|      struct icmp6 *icmp6 = (struct icmp6 *) (ip6 + 1);
   65|       |      // send all handled ICMPv6 types, then 2 random ones
   66|     25|      if (st->icmp6_type >= (sizeof(icmp6_types) / sizeof(icmp6_types[0]) + 2)) st->icmp6_type = 0;
  ------------------
  |  Branch (66:11): [True: 0, False: 25]
  ------------------
   67|     25|      if (st->icmp6_type < (sizeof(icmp6_types) / sizeof(icmp6_types[0]))) icmp6->type = icmp6_types[st->icmp6_type++];
  ------------------
  |  Branch (67:11): [True: 8, False: 17]
  ------------------
   68|     25|    }
   69|     67|  }
   70|     67|}
fuzz.c:_ZL2fnP13mg_connectioniPv:
   19|   458k|static void fn(struct mg_connection *c, int ev, void *ev_data) {
   20|   458k|  struct mg_http_serve_opts opts = {.root_dir = "."};
   21|   458k|  if (ev == MG_EV_HTTP_MSG) {
  ------------------
  |  Branch (21:7): [True: 214k, False: 244k]
  ------------------
   22|   214k|    mg_http_serve_dir(c, (struct mg_http_message *) ev_data, &opts);
   23|   214k|  }
   24|   458k|}

mg_base64_update:
   65|   191M|size_t mg_base64_update(unsigned char ch, char *to, size_t n) {
   66|   191M|  unsigned long rem = (n & 3) % 3;
   67|   191M|  if (rem == 0) {
  ------------------
  |  Branch (67:7): [True: 63.6M, False: 127M]
  ------------------
   68|  63.6M|    to[n] = (char) mg_base64_encode_single(ch >> 2);
   69|  63.6M|    to[++n] = (char) ((ch & 3) << 4);
   70|   127M|  } else if (rem == 1) {
  ------------------
  |  Branch (70:14): [True: 63.6M, False: 63.6M]
  ------------------
   71|  63.6M|    to[n] = (char) mg_base64_encode_single(to[n] | (ch >> 4));
   72|  63.6M|    to[++n] = (char) ((ch & 15) << 2);
   73|  63.6M|  } else {
   74|  63.6M|    to[n] = (char) mg_base64_encode_single(to[n] | (ch >> 6));
   75|  63.6M|    to[++n] = (char) mg_base64_encode_single(ch & 63);
   76|  63.6M|    n++;
   77|  63.6M|  }
   78|   191M|  return n;
   79|   191M|}
mg_base64_final:
   81|  11.1k|size_t mg_base64_final(char *to, size_t n) {
   82|  11.1k|  size_t saved = n;
   83|       |  // printf("---[%.*s]\n", n, to);
   84|  11.1k|  if (n & 3) n = mg_base64_update(0, to, n);
  ------------------
  |  Branch (84:7): [True: 3.68k, False: 7.46k]
  ------------------
   85|  11.1k|  if ((saved & 3) == 2) n--;
  ------------------
  |  Branch (85:7): [True: 1.76k, False: 9.39k]
  ------------------
   86|       |  // printf("    %d[%.*s]\n", n, n, to);
   87|  16.7k|  while (n & 3) to[n++] = '=';
  ------------------
  |  Branch (87:10): [True: 5.60k, False: 11.1k]
  ------------------
   88|  11.1k|  to[n] = '\0';
   89|  11.1k|  return n;
   90|  11.1k|}
mg_base64_encode:
   92|  11.1k|size_t mg_base64_encode(const unsigned char *p, size_t n, char *to, size_t dl) {
   93|  11.1k|  size_t i, len = 0;
   94|  11.1k|  if (dl > 0) to[0] = '\0';
  ------------------
  |  Branch (94:7): [True: 11.1k, False: 0]
  ------------------
   95|  11.1k|  if (dl < ((n / 3) + (n % 3 ? 1 : 0)) * 4 + 1) return 0;
  ------------------
  |  Branch (95:7): [True: 0, False: 11.1k]
  |  Branch (95:24): [True: 3.68k, False: 7.46k]
  ------------------
   96|   191M|  for (i = 0; i < n; i++) len = mg_base64_update(p[i], to, len);
  ------------------
  |  Branch (96:15): [True: 191M, False: 11.1k]
  ------------------
   97|  11.1k|  len = mg_base64_final(to, len);
   98|  11.1k|  return len;
   99|  11.1k|}
mg_base64_decode:
  101|  11.1k|size_t mg_base64_decode(const char *src, size_t n, char *dst, size_t dl) {
  102|  11.1k|  const char *end = src == NULL ? NULL : src + n;  // Cannot add to NULL
  ------------------
  |  Branch (102:21): [True: 5.57k, False: 5.57k]
  ------------------
  103|  11.1k|  size_t len = 0;
  104|  11.1k|  if (dl < n / 4 * 3 + 1) goto fail;
  ------------------
  |  Branch (104:7): [True: 0, False: 11.1k]
  ------------------
  105|   602k|  while (src != NULL && src + 3 < end) {
  ------------------
  |  Branch (105:10): [True: 597k, False: 5.57k]
  |  Branch (105:25): [True: 596k, False: 563]
  ------------------
  106|   596k|    int a = mg_base64_decode_single(src[0]),
  107|   596k|        b = mg_base64_decode_single(src[1]),
  108|   596k|        c = mg_base64_decode_single(src[2]),
  109|   596k|        d = mg_base64_decode_single(src[3]);
  110|   596k|    if (a == 64 || a < 0 || b == 64 || b < 0 || c < 0 || d < 0) {
  ------------------
  |  Branch (110:9): [True: 11, False: 596k]
  |  Branch (110:20): [True: 2.33k, False: 594k]
  |  Branch (110:29): [True: 4, False: 594k]
  |  Branch (110:40): [True: 1.04k, False: 593k]
  |  Branch (110:49): [True: 1.39k, False: 591k]
  |  Branch (110:58): [True: 220, False: 591k]
  ------------------
  111|  5.01k|      goto fail;
  112|  5.01k|    }
  113|   591k|    dst[len++] = (char) ((a << 2) | (b >> 4));
  114|   591k|    if (src[2] != '=') {
  ------------------
  |  Branch (114:9): [True: 591k, False: 222]
  ------------------
  115|   591k|      dst[len++] = (char) ((b << 4) | (c >> 2));
  116|   591k|      if (src[3] != '=') dst[len++] = (char) ((c << 6) | d);
  ------------------
  |  Branch (116:11): [True: 591k, False: 256]
  ------------------
  117|   591k|    }
  118|   591k|    src += 4;
  119|   591k|  }
  120|  6.14k|  dst[len] = '\0';
  121|  6.14k|  return len;
  122|  5.01k|fail:
  123|  5.01k|  if (dl > 0) dst[0] = '\0';
  ------------------
  |  Branch (123:7): [True: 5.01k, False: 0]
  ------------------
  124|  5.01k|  return 0;
  125|  11.1k|}
mg_resolve_cancel:
 1838|  5.57k|void mg_resolve_cancel(struct mg_connection *c) {
 1839|  5.57k|  struct dns_data *tmp, *d;
 1840|  5.57k|  struct mdns_data *mtmp, *md;
 1841|  5.57k|  struct dns_data **head = (struct dns_data **) &c->mgr->active_dns_requests;
 1842|  5.57k|  struct mdns_data **mhead =
 1843|  5.57k|      (struct mdns_data **) &c->mgr->active_mdns_requests;
 1844|  5.57k|  for (d = *head; d != NULL; d = tmp) {
  ------------------
  |  Branch (1844:19): [True: 0, False: 5.57k]
  ------------------
 1845|      0|    tmp = d->next;
 1846|      0|    if (d->c == c) dns_free(head, d);
  ------------------
  |  Branch (1846:9): [True: 0, False: 0]
  ------------------
 1847|      0|  }
 1848|  5.57k|  for (md = *mhead; md != NULL; md = mtmp) {
  ------------------
  |  Branch (1848:21): [True: 0, False: 5.57k]
  ------------------
 1849|      0|    mtmp = md->next;
 1850|      0|    if (md->c == c) mdns_free(mhead, md);
  ------------------
  |  Branch (1850:9): [True: 0, False: 0]
  ------------------
 1851|      0|  }
 1852|  5.57k|}
mg_dns_parse_rr:
 1897|    690|                       bool is_question, struct mg_dns_rr *rr) {
 1898|    690|  const uint8_t *s = buf + ofs, *e = &buf[len];
 1899|       |
 1900|    690|  memset(rr, 0, sizeof(*rr));
 1901|    690|  if (len < sizeof(struct mg_dns_header)) return 0;  // Too small
  ------------------
  |  Branch (1901:7): [True: 0, False: 690]
  ------------------
 1902|    690|  if (len > 512) return 0;  //  Too large, we don't expect that
  ------------------
  |  Branch (1902:7): [True: 42, False: 648]
  ------------------
 1903|    648|  if (s >= e) return 0;     //  Overflow
  ------------------
  |  Branch (1903:7): [True: 94, False: 554]
  ------------------
 1904|       |
 1905|    554|  if ((rr->nlen = (uint16_t) mg_dns_parse_name(buf, len, ofs, NULL, 0)) == 0)
  ------------------
  |  Branch (1905:7): [True: 65, False: 489]
  ------------------
 1906|     65|    return 0;
 1907|    489|  s += rr->nlen + 4;
 1908|    489|  if (s > e) return 0;
  ------------------
  |  Branch (1908:7): [True: 69, False: 420]
  ------------------
 1909|    420|  rr->atype = (uint16_t) (((uint16_t) s[-4] << 8) | s[-3]);
 1910|    420|  rr->aclass = (uint16_t) (((uint16_t) s[-2] << 8) | s[-1]);
 1911|    420|  if (is_question) return (size_t) (rr->nlen + 4);
  ------------------
  |  Branch (1911:7): [True: 82, False: 338]
  ------------------
 1912|       |
 1913|    338|  s += 6;
 1914|    338|  if (s > e) return 0;
  ------------------
  |  Branch (1914:7): [True: 20, False: 318]
  ------------------
 1915|    318|  rr->alen = (uint16_t) (((uint16_t) s[-2] << 8) | s[-1]);
 1916|    318|  if (s + rr->alen > e) return 0;
  ------------------
  |  Branch (1916:7): [True: 40, False: 278]
  ------------------
 1917|    278|  return (size_t) (rr->nlen + rr->alen + 10);
 1918|    318|}
mg_dns_parse:
 1920|  11.1k|bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
 1921|  11.1k|  const struct mg_dns_header *h = (struct mg_dns_header *) buf;
 1922|  11.1k|  struct mg_dns_rr rr;
 1923|  11.1k|  size_t i, n, num_answers, ofs = sizeof(*h);
 1924|  11.1k|  bool is_response;
 1925|  11.1k|  memset(dm, 0, sizeof(*dm));
 1926|       |
 1927|  11.1k|  if (len < sizeof(*h)) return 0;                // Too small, headers dont fit
  ------------------
  |  Branch (1927:7): [True: 6.85k, False: 4.30k]
  ------------------
 1928|  4.30k|  if (mg_ntohs(h->num_questions) > 1) return 0;  // Sanity
  ------------------
  |  Branch (1928:7): [True: 3.89k, False: 409]
  ------------------
 1929|    409|  num_answers = mg_ntohs(h->num_answers);
 1930|    409|  if (num_answers > 10) {
  ------------------
  |  Branch (1930:7): [True: 321, False: 88]
  ------------------
 1931|    321|    MG_DEBUG(("Got %u answers, ignoring beyond 10th one", num_answers));
  ------------------
  |  | 1825|    321|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|    321|  do {                      \
  |  |  |  | 1814|    321|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 321]
  |  |  |  |  ------------------
  |  |  |  | 1815|    321|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 321]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1932|    321|    num_answers = 10;  // Sanity cap
 1933|    321|  }
 1934|    409|  dm->txnid = mg_ntohs(h->txnid);
 1935|    409|  is_response = mg_ntohs(h->flags) & 0x8000;
 1936|       |
 1937|    491|  for (i = 0; i < mg_ntohs(h->num_questions); i++) {
  ------------------
  |  Branch (1937:15): [True: 166, False: 325]
  ------------------
 1938|    166|    if ((n = mg_dns_parse_rr(buf, len, ofs, true, &rr)) == 0) return false;
  ------------------
  |  Branch (1938:9): [True: 84, False: 82]
  ------------------
 1939|       |    // MG_INFO(("Q %lu %lu %hu/%hu", ofs, n, rr.atype, rr.aclass));
 1940|     82|    mg_dns_parse_name(buf, len, ofs, dm->name, sizeof(dm->name));
 1941|     82|    ofs += n;
 1942|     82|  }
 1943|       |
 1944|    325|  if (!is_response) {
  ------------------
  |  Branch (1944:7): [True: 50, False: 275]
  ------------------
 1945|       |    // For queries, there is no need to parse the answers. In this way,
 1946|       |    // we also ensure the domain name (dm->name) is parsed from
 1947|       |    // the question field.
 1948|     50|    return true;
 1949|     50|  }
 1950|       |
 1951|    551|  for (i = 0; i < num_answers; i++) {
  ------------------
  |  Branch (1951:15): [True: 524, False: 27]
  ------------------
 1952|    524|    if ((n = mg_dns_parse_rr(buf, len, ofs, false, &rr)) == 0) return false;
  ------------------
  |  Branch (1952:9): [True: 246, False: 278]
  ------------------
 1953|       |    // MG_INFO(("A -- %lu %lu %hu/%hu %s", ofs, n, rr.atype, rr.aclass,
 1954|       |    // dm->name));
 1955|    278|    mg_dns_parse_name(buf, len, ofs, dm->name, sizeof(dm->name));
 1956|    278|    ofs += n;
 1957|       |
 1958|    278|    if (rr.alen == 4 && rr.atype == MG_DNS_RTYPE_A && rr.aclass == 1) {
  ------------------
  |  | 3755|    352|#define MG_DNS_RTYPE_A 1     // IPv4 address (4 bytes)
  ------------------
  |  Branch (1958:9): [True: 74, False: 204]
  |  Branch (1958:25): [True: 34, False: 40]
  |  Branch (1958:55): [True: 1, False: 33]
  ------------------
 1959|      1|      dm->addr.is_ip6 = false;
 1960|      1|      memcpy(&dm->addr.addr.ip, &buf[ofs - 4], 4);
 1961|      1|      dm->resolved = true;
 1962|      1|      break;  // Return success
 1963|    277|    } else if (rr.alen == 16 && rr.atype == MG_DNS_RTYPE_AAAA &&
  ------------------
  |  | 3758|    333|#define MG_DNS_RTYPE_AAAA 28 // IPv6 address (16 bytes)
  ------------------
  |  Branch (1963:16): [True: 56, False: 221]
  |  Branch (1963:33): [True: 28, False: 28]
  ------------------
 1964|     28|               rr.aclass == 1) {
  ------------------
  |  Branch (1964:16): [True: 1, False: 27]
  ------------------
 1965|      1|      dm->addr.is_ip6 = true;
 1966|      1|      memcpy(&dm->addr.addr.ip, &buf[ofs - 16], 16);
 1967|      1|      dm->resolved = true;
 1968|      1|      break;  // Return success
 1969|      1|    }
 1970|    278|  }
 1971|     29|  return true;
 1972|    275|}
mg_resolve:
 2102|  5.57k|void mg_resolve(struct mg_connection *c, const char *url) {
 2103|  5.57k|  struct mg_str host = mg_url_host(url);
 2104|  5.57k|  c->rem.port = mg_htons(mg_url_port(url));
  ------------------
  |  | 2094|  5.57k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 2105|  5.57k|  if (mg_aton(host, &c->rem)) {
  ------------------
  |  Branch (2105:7): [True: 5.57k, False: 0]
  ------------------
 2106|       |    // host is an IP address, do not fire name resolution
 2107|  5.57k|    mg_connect_resolved(c);
 2108|  5.57k|  } else if (host.len > 6 &&
  ------------------
  |  Branch (2108:14): [True: 0, False: 0]
  ------------------
 2109|      0|             strncmp(".local", &host.buf[host.len - 6], 6) == 0) {
  ------------------
  |  Branch (2109:14): [True: 0, False: 0]
  ------------------
 2110|       |    // this is a request for a .local name (mDNS)
 2111|      0|    sendmdnsreq(c, &host, 500, c->mgr->mdns, c->mgr->use_dns6);  // 500ms tmout
 2112|      0|  } else {
 2113|       |    // host is not an IP nor a .local, send DNS resolution request
 2114|      0|    struct mg_dns *dns = c->mgr->use_dns6 ? &c->mgr->dns6 : &c->mgr->dns4;
  ------------------
  |  Branch (2114:26): [True: 0, False: 0]
  ------------------
 2115|      0|    sendnsreq(c, &host, c->mgr->dnstimeout, dns, c->mgr->use_dns6);
 2116|      0|  }
 2117|  5.57k|}
mg_call:
 2638|   458k|void mg_call(struct mg_connection *c, int ev, void *ev_data) {
 2639|       |#if MG_ENABLE_PROFILE
 2640|       |  const char *names[] = {
 2641|       |      "EV_ERROR",    "EV_OPEN",      "EV_POLL",      "EV_RESOLVE",
 2642|       |      "EV_CONNECT",  "EV_ACCEPT",    "EV_TLS_HS",    "EV_READ",
 2643|       |      "EV_WRITE",    "EV_CLOSE",     "EV_HTTP_MSG",  "EV_HTTP_CHUNK",
 2644|       |      "EV_WS_OPEN",  "EV_WS_MSG",    "EV_WS_CTL",    "EV_MQTT_CMD",
 2645|       |      "EV_MQTT_MSG", "EV_MQTT_OPEN", "EV_SNTP_TIME", "EV_USER"};
 2646|       |  if (ev != MG_EV_POLL && ev < (int) (sizeof(names) / sizeof(names[0]))) {
 2647|       |    MG_PROF_ADD(c, names[ev]);
 2648|       |  }
 2649|       |#endif
 2650|       |  // Fire protocol handler first, user handler second. See #2559
 2651|   458k|  if (c->pfn != NULL) c->pfn(c, ev, ev_data);
  ------------------
  |  Branch (2651:7): [True: 458k, False: 0]
  ------------------
 2652|   458k|  if (c->fn != NULL) c->fn(c, ev, ev_data);
  ------------------
  |  Branch (2652:7): [True: 458k, False: 0]
  ------------------
 2653|   458k|}
mg_error:
 2655|    596|void mg_error(struct mg_connection *c, const char *fmt, ...) {
 2656|    596|  char buf[64];
 2657|    596|  va_list ap;
 2658|    596|  va_start(ap, fmt);
 2659|    596|  mg_vsnprintf(buf, sizeof(buf), fmt, &ap);
 2660|    596|  va_end(ap);
 2661|    596|  MG_ERROR(("%lu %ld %s", c->id, c->fd, buf));
  ------------------
  |  | 1823|    596|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|    596|  do {                      \
  |  |  |  | 1814|    596|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 596]
  |  |  |  |  ------------------
  |  |  |  | 1815|    596|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 596]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2662|    596|  c->is_closing = 1;             // Set is_closing before sending MG_EV_CALL
 2663|    596|  mg_call(c, MG_EV_ERROR, buf);  // Let user handler override it
 2664|    596|}
mg_vxprintf:
 2920|  1.40M|                   va_list *ap) {
 2921|  1.40M|  size_t i = 0, n = 0;
 2922|  20.7M|  while (fmt[i] != '\0') {
  ------------------
  |  Branch (2922:10): [True: 19.3M, False: 1.40M]
  ------------------
 2923|  19.3M|    if (fmt[i] == '%') {
  ------------------
  |  Branch (2923:9): [True: 1.06M, False: 18.2M]
  ------------------
 2924|  1.06M|      size_t j, k, x = 0, is_long = 0, w = 0 /* width */, pr = ~0U /* prec */;
 2925|  1.06M|      char pad = ' ', minus = 0, c = fmt[++i];
 2926|  1.06M|      if (c == '#') x++, c = fmt[++i];
  ------------------
  |  Branch (2926:11): [True: 0, False: 1.06M]
  ------------------
 2927|  1.06M|      if (c == '-') minus++, c = fmt[++i];
  ------------------
  |  Branch (2927:11): [True: 210k, False: 849k]
  ------------------
 2928|  1.06M|      if (c == '0') pad = '0', c = fmt[++i];
  ------------------
  |  Branch (2928:11): [True: 0, False: 1.06M]
  ------------------
 2929|  1.48M|      while (is_digit(c)) w *= 10, w += (size_t) (c - '0'), c = fmt[++i];
  ------------------
  |  Branch (2929:14): [True: 420k, False: 1.06M]
  ------------------
 2930|  1.06M|      if (c == '.') {
  ------------------
  |  Branch (2930:11): [True: 218k, False: 841k]
  ------------------
 2931|   218k|        c = fmt[++i];
 2932|   218k|        if (c == '*') {
  ------------------
  |  Branch (2932:13): [True: 218k, False: 0]
  ------------------
 2933|   218k|          pr = (size_t) va_arg(*ap, int);
 2934|   218k|          c = fmt[++i];
 2935|   218k|        } else {
 2936|      0|          pr = 0;
 2937|      0|          while (is_digit(c)) pr *= 10, pr += (size_t) (c - '0'), c = fmt[++i];
  ------------------
  |  Branch (2937:18): [True: 0, False: 0]
  ------------------
 2938|      0|        }
 2939|   218k|      }
 2940|  1.06M|      while (c == 'h') c = fmt[++i];  // Treat h and hh as int
  ------------------
  |  Branch (2940:14): [True: 0, False: 1.06M]
  ------------------
 2941|  1.06M|      if (c == 'l') {
  ------------------
  |  Branch (2941:11): [True: 210k, False: 849k]
  ------------------
 2942|   210k|        is_long++, c = fmt[++i];
 2943|   210k|        if (c == 'l') is_long++, c = fmt[++i];
  ------------------
  |  Branch (2943:13): [True: 0, False: 210k]
  ------------------
 2944|   210k|      }
 2945|  1.06M|      if (c == 'z') is_long = 1, c = fmt[++i];
  ------------------
  |  Branch (2945:11): [True: 0, False: 1.06M]
  ------------------
 2946|  1.06M|      if (c == 'p') x = 1, is_long = 1;
  ------------------
  |  Branch (2946:11): [True: 0, False: 1.06M]
  ------------------
 2947|  1.06M|      if (c == 'd' || c == 'u' || c == 'x' || c == 'X' || c == 'p' ||
  ------------------
  |  Branch (2947:11): [True: 210k, False: 849k]
  |  Branch (2947:23): [True: 210k, False: 639k]
  |  Branch (2947:35): [True: 0, False: 639k]
  |  Branch (2947:47): [True: 0, False: 639k]
  |  Branch (2947:59): [True: 0, False: 639k]
  ------------------
 2948|   639k|          c == 'g' || c == 'f') {
  ------------------
  |  Branch (2948:11): [True: 0, False: 639k]
  |  Branch (2948:23): [True: 0, False: 639k]
  ------------------
 2949|   420k|        bool s = (c == 'd'), h = (c == 'x' || c == 'X' || c == 'p');
  ------------------
  |  Branch (2949:35): [True: 0, False: 420k]
  |  Branch (2949:47): [True: 0, False: 420k]
  |  Branch (2949:59): [True: 0, False: 420k]
  ------------------
 2950|   420k|        char tmp[40];
 2951|   420k|        size_t xl = x ? 2 : 0;
  ------------------
  |  Branch (2951:21): [True: 0, False: 420k]
  ------------------
 2952|   420k|        if (c == 'g' || c == 'f') {
  ------------------
  |  Branch (2952:13): [True: 0, False: 420k]
  |  Branch (2952:25): [True: 0, False: 420k]
  ------------------
 2953|      0|          double v = va_arg(*ap, double);
 2954|      0|          if (pr == ~0U) pr = 6;
  ------------------
  |  Branch (2954:15): [True: 0, False: 0]
  ------------------
 2955|      0|          k = mg_dtoa(tmp, sizeof(tmp), v, (int) pr, c == 'g');
 2956|   420k|        } else if (is_long == 2) {
  ------------------
  |  Branch (2956:20): [True: 0, False: 420k]
  ------------------
 2957|      0|          int64_t v = va_arg(*ap, int64_t);
 2958|      0|          k = mg_lld(tmp, v, s, h);
 2959|   420k|        } else if (is_long == 1) {
  ------------------
  |  Branch (2959:20): [True: 210k, False: 210k]
  ------------------
 2960|   210k|          long v = va_arg(*ap, long);
 2961|   210k|          k = mg_lld(tmp, s ? (int64_t) v : (int64_t) (unsigned long) v, s, h);
  ------------------
  |  Branch (2961:27): [True: 0, False: 210k]
  ------------------
 2962|   210k|        } else {
 2963|   210k|          int v = va_arg(*ap, int);
 2964|   210k|          k = mg_lld(tmp, s ? (int64_t) v : (int64_t) (unsigned) v, s, h);
  ------------------
  |  Branch (2964:27): [True: 210k, False: 0]
  ------------------
 2965|   210k|        }
 2966|   420k|        for (j = 0; j < xl && w > 0; j++) w--;
  ------------------
  |  Branch (2966:21): [True: 0, False: 420k]
  |  Branch (2966:31): [True: 0, False: 0]
  ------------------
 2967|   420k|        for (j = 0; pad == ' ' && !minus && k < w && j + k < w; j++)
  ------------------
  |  Branch (2967:21): [True: 420k, False: 0]
  |  Branch (2967:35): [True: 210k, False: 210k]
  |  Branch (2967:45): [True: 0, False: 210k]
  |  Branch (2967:54): [True: 0, False: 0]
  ------------------
 2968|      0|          n += scpy(out, param, &pad, 1);
 2969|   420k|        n += scpy(out, param, (char *) "0x", xl);
 2970|   420k|        for (j = 0; pad == '0' && k < w && j + k < w; j++)
  ------------------
  |  Branch (2970:21): [True: 0, False: 420k]
  |  Branch (2970:35): [True: 0, False: 0]
  |  Branch (2970:44): [True: 0, False: 0]
  ------------------
 2971|      0|          n += scpy(out, param, &pad, 1);
 2972|   420k|        n += scpy(out, param, tmp, k);
 2973|  2.10M|        for (j = 0; pad == ' ' && minus && k < w && j + k < w; j++)
  ------------------
  |  Branch (2973:21): [True: 2.10M, False: 0]
  |  Branch (2973:35): [True: 1.89M, False: 210k]
  |  Branch (2973:44): [True: 1.89M, False: 0]
  |  Branch (2973:53): [True: 1.68M, False: 210k]
  ------------------
 2974|  1.68M|          n += scpy(out, param, &pad, 1);
 2975|   639k|      } else if (c == 'm' || c == 'M') {
  ------------------
  |  Branch (2975:18): [True: 0, False: 639k]
  |  Branch (2975:30): [True: 0, False: 639k]
  ------------------
 2976|      0|        mg_pm_t f = va_arg(*ap, mg_pm_t);
 2977|      0|        if (c == 'm') out('"', param);
  ------------------
  |  Branch (2977:13): [True: 0, False: 0]
  ------------------
 2978|      0|        n += f(out, param, ap);
 2979|      0|        if (c == 'm') n += 2, out('"', param);
  ------------------
  |  Branch (2979:13): [True: 0, False: 0]
  ------------------
 2980|   639k|      } else if (c == 'c') {
  ------------------
  |  Branch (2980:18): [True: 0, False: 639k]
  ------------------
 2981|      0|        int ch = va_arg(*ap, int);
 2982|      0|        out((char) ch, param);
 2983|      0|        n++;
 2984|   639k|      } else if (c == 's') {
  ------------------
  |  Branch (2984:18): [True: 639k, False: 0]
  ------------------
 2985|   639k|        char *p = va_arg(*ap, char *);
 2986|   639k|        if (pr == ~0U) pr = p == NULL ? 0 : strlen(p);
  ------------------
  |  Branch (2986:13): [True: 420k, False: 218k]
  |  Branch (2986:29): [True: 0, False: 420k]
  ------------------
 2987|   639k|        for (j = 0; !minus && pr < w && j + pr < w; j++)
  ------------------
  |  Branch (2987:21): [True: 639k, False: 0]
  |  Branch (2987:31): [True: 0, False: 639k]
  |  Branch (2987:41): [True: 0, False: 0]
  ------------------
 2988|      0|          n += scpy(out, param, &pad, 1);
 2989|   639k|        n += scpy(out, param, p, pr);
 2990|   639k|        for (j = 0; minus && pr < w && j + pr < w; j++)
  ------------------
  |  Branch (2990:21): [True: 0, False: 639k]
  |  Branch (2990:30): [True: 0, False: 0]
  |  Branch (2990:40): [True: 0, False: 0]
  ------------------
 2991|      0|          n += scpy(out, param, &pad, 1);
 2992|   639k|      } else if (c == '%') {
  ------------------
  |  Branch (2992:18): [True: 0, False: 0]
  ------------------
 2993|      0|        out('%', param);
 2994|      0|        n++;
 2995|      0|      } else {
 2996|      0|        out('%', param);
 2997|      0|        out(c, param);
 2998|      0|        n += 2;
 2999|      0|      }
 3000|  1.06M|      i++;
 3001|  18.2M|    } else {
 3002|  18.2M|      out(fmt[i], param), n++, i++;
 3003|  18.2M|    }
 3004|  19.3M|  }
 3005|  1.40M|  return n;
 3006|  1.40M|}
mg_fs_open:
 3017|  21.8k|struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags) {
 3018|  21.8k|  struct mg_fd *fd = (struct mg_fd *) mg_calloc(1, sizeof(*fd));
 3019|  21.8k|  if (fd != NULL) {
  ------------------
  |  Branch (3019:7): [True: 21.8k, False: 0]
  ------------------
 3020|  21.8k|    fd->fd = fs->op(path, flags);
 3021|  21.8k|    fd->fs = fs;
 3022|  21.8k|    if (fd->fd == NULL) {
  ------------------
  |  Branch (3022:9): [True: 21.8k, False: 0]
  ------------------
 3023|  21.8k|      mg_free(fd);
 3024|       |      fd = NULL;
 3025|  21.8k|    }
 3026|  21.8k|  }
 3027|  21.8k|  return fd;
 3028|  21.8k|}
mg_fs_close:
 3030|  21.5k|void mg_fs_close(struct mg_fd *fd) {
 3031|  21.5k|  if (fd != NULL) {
  ------------------
  |  Branch (3031:7): [True: 0, False: 21.5k]
  ------------------
 3032|      0|    fd->fs->cl(fd->fd);
 3033|      0|    mg_free(fd);
 3034|      0|  }
 3035|  21.5k|}
_Z12mg_to_size_t6mg_strPm:
 3788|  1.86k|bool mg_to_size_t(struct mg_str str, size_t *val) {
 3789|  1.86k|  size_t i = 0, max = (size_t) -1, max2 = max / 10, result = 0, ndigits = 0;
 3790|  1.86k|  while (i < str.len && (str.buf[i] == ' ' || str.buf[i] == '\t')) i++;
  ------------------
  |  Branch (3790:10): [True: 1.85k, False: 12]
  |  Branch (3790:26): [True: 0, False: 1.85k]
  |  Branch (3790:47): [True: 0, False: 1.85k]
  ------------------
 3791|  1.86k|  if (i < str.len && str.buf[i] == '-') return false;
  ------------------
  |  Branch (3791:7): [True: 1.85k, False: 12]
  |  Branch (3791:22): [True: 11, False: 1.84k]
  ------------------
 3792|  11.4M|  while (i < str.len && str.buf[i] >= '0' && str.buf[i] <= '9') {
  ------------------
  |  Branch (3792:10): [True: 11.4M, False: 1.67k]
  |  Branch (3792:25): [True: 11.4M, False: 126]
  |  Branch (3792:46): [True: 11.4M, False: 31]
  ------------------
 3793|  11.4M|    size_t digit = (size_t) (str.buf[i] - '0');
 3794|  11.4M|    if (result > max2) return false;  // Overflow
  ------------------
  |  Branch (3794:9): [True: 21, False: 11.4M]
  ------------------
 3795|  11.4M|    result *= 10;
 3796|  11.4M|    if (result > max - digit) return false;  // Overflow
  ------------------
  |  Branch (3796:9): [True: 3, False: 11.4M]
  ------------------
 3797|  11.4M|    result += digit;
 3798|  11.4M|    i++, ndigits++;
 3799|  11.4M|  }
 3800|  4.25k|  while (i < str.len && (str.buf[i] == ' ' || str.buf[i] == '\t')) i++;
  ------------------
  |  Branch (3800:10): [True: 2.57k, False: 1.67k]
  |  Branch (3800:26): [True: 1.28k, False: 1.29k]
  |  Branch (3800:47): [True: 1.13k, False: 157]
  ------------------
 3801|  1.83k|  if (ndigits == 0) return false;  // #2322: Content-Length = 1 * DIGIT
  ------------------
  |  Branch (3801:7): [True: 37, False: 1.79k]
  ------------------
 3802|  1.79k|  if (i != str.len) return false;  // Ditto
  ------------------
  |  Branch (3802:7): [True: 132, False: 1.66k]
  ------------------
 3803|  1.66k|  *val = (size_t) result;
 3804|  1.66k|  return true;
 3805|  1.79k|}
mg_http_var:
 3888|  5.57k|struct mg_str mg_http_var(struct mg_str buf, struct mg_str name) {
 3889|  5.57k|  struct mg_str entry, k, v, result = mg_str_n(NULL, 0);
 3890|   110k|  while (mg_span(buf, &entry, &buf, '&')) {
  ------------------
  |  Branch (3890:10): [True: 105k, False: 5.54k]
  ------------------
 3891|   105k|    if (mg_span(entry, &k, &v, '=') && name.len == k.len &&
  ------------------
  |  Branch (3891:9): [True: 102k, False: 2.94k]
  |  Branch (3891:40): [True: 38.9k, False: 63.2k]
  ------------------
 3892|  38.9k|        mg_ncasecmp(name.buf, k.buf, k.len) == 0) {
  ------------------
  |  Branch (3892:9): [True: 36, False: 38.9k]
  ------------------
 3893|     36|      result = v;
 3894|     36|      break;
 3895|     36|    }
 3896|   105k|  }
 3897|  5.57k|  return result;
 3898|  5.57k|}
mg_http_get_var:
 3901|  11.1k|                    size_t dst_len) {
 3902|  11.1k|  int len;
 3903|  11.1k|  if (dst != NULL && dst_len > 0) {
  ------------------
  |  Branch (3903:7): [True: 5.57k, False: 5.57k]
  |  Branch (3903:22): [True: 5.57k, False: 0]
  ------------------
 3904|  5.57k|    dst[0] = '\0';  // If destination buffer is valid, always nul-terminate it
 3905|  5.57k|  }
 3906|  11.1k|  if (dst == NULL || dst_len == 0) {
  ------------------
  |  Branch (3906:7): [True: 5.57k, False: 5.57k]
  |  Branch (3906:22): [True: 0, False: 5.57k]
  ------------------
 3907|  5.57k|    len = -2;  // Bad destination
 3908|  5.57k|  } else if (buf->buf == NULL || name == NULL || buf->len == 0) {
  ------------------
  |  Branch (3908:14): [True: 0, False: 5.57k]
  |  Branch (3908:34): [True: 0, False: 5.57k]
  |  Branch (3908:50): [True: 0, False: 5.57k]
  ------------------
 3909|      0|    len = -1;  // Bad source
 3910|  5.57k|  } else {
 3911|  5.57k|    struct mg_str v = mg_http_var(*buf, mg_str(name));
  ------------------
  |  | 1524|  5.57k|#define mg_str(s) mg_str_s(s)
  ------------------
 3912|  5.57k|    if (v.buf == NULL) {
  ------------------
  |  Branch (3912:9): [True: 5.54k, False: 36]
  ------------------
 3913|  5.54k|      len = -4;  // Name does not exist
 3914|  5.54k|    } else {
 3915|     36|      len = mg_url_decode(v.buf, v.len, dst, dst_len, 1);
 3916|     36|      if (len < 0) len = -3;  // Failed to decode
  ------------------
  |  Branch (3916:11): [True: 13, False: 23]
  ------------------
 3917|     36|    }
 3918|  5.57k|  }
 3919|  11.1k|  return len;
 3920|  11.1k|}
mg_url_decode:
 3928|   231k|                  int is_form_url_encoded) {
 3929|   231k|  size_t i, j;
 3930|  5.31M|  for (i = j = 0; i < src_len && j + 1 < dst_len; i++, j++) {
  ------------------
  |  Branch (3930:19): [True: 5.09M, False: 217k]
  |  Branch (3930:34): [True: 5.08M, False: 6.99k]
  ------------------
 3931|  5.08M|    if (src[i] == '%') {
  ------------------
  |  Branch (3931:9): [True: 52.7k, False: 5.03M]
  ------------------
 3932|       |      // Use `i + 2 < src_len`, not `i < src_len - 2`, note small src_len
 3933|  52.7k|      if (i + 2 < src_len && isx(src[i + 1]) && isx(src[i + 2])) {
  ------------------
  |  Branch (3933:11): [True: 52.2k, False: 495]
  |  Branch (3933:30): [True: 48.0k, False: 4.19k]
  |  Branch (3933:49): [True: 46.4k, False: 1.62k]
  ------------------
 3934|  46.4k|        mg_str_to_num(mg_str_n(src + i + 1, 2), 16, &dst[j], sizeof(uint8_t));
 3935|  46.4k|        i += 2;
 3936|  46.4k|      } else {
 3937|  6.32k|        dst[0] = '\0';
 3938|  6.32k|        return -1;
 3939|  6.32k|      }
 3940|  5.03M|    } else if (is_form_url_encoded && src[i] == '+') {
  ------------------
  |  Branch (3940:16): [True: 449k, False: 4.58M]
  |  Branch (3940:39): [True: 3.02k, False: 446k]
  ------------------
 3941|  3.02k|      dst[j] = ' ';
 3942|  5.03M|    } else {
 3943|  5.03M|      dst[j] = src[i];
 3944|  5.03M|    }
 3945|  5.08M|  }
 3946|   224k|  if (j < dst_len) dst[j] = '\0';  // Null-terminate the destination
  ------------------
  |  Branch (3946:7): [True: 224k, False: 0]
  ------------------
 3947|   224k|  return i >= src_len && j < dst_len ? (int) j : -1;
  ------------------
  |  Branch (3947:10): [True: 217k, False: 6.99k]
  |  Branch (3947:26): [True: 217k, False: 0]
  ------------------
 3948|   231k|}
mg_http_get_request_len:
 3954|   232k|int mg_http_get_request_len(const unsigned char *buf, size_t buf_len) {
 3955|   232k|  size_t i;
 3956|   211M|  for (i = 0; i < buf_len; i++) {
  ------------------
  |  Branch (3956:15): [True: 211M, False: 9.73k]
  ------------------
 3957|   211M|    if (!isok(buf[i])) return -1;
  ------------------
  |  Branch (3957:9): [True: 3.29k, False: 211M]
  ------------------
 3958|   211M|    if ((i > 0 && buf[i] == '\n' && buf[i - 1] == '\n') ||
  ------------------
  |  Branch (3958:10): [True: 210M, False: 226k]
  |  Branch (3958:19): [True: 592k, False: 210M]
  |  Branch (3958:37): [True: 218k, False: 373k]
  ------------------
 3959|   210M|        (i > 3 && buf[i] == '\n' && buf[i - 1] == '\r' && buf[i - 2] == '\n'))
  ------------------
  |  Branch (3959:10): [True: 209M, False: 899k]
  |  Branch (3959:19): [True: 373k, False: 209M]
  |  Branch (3959:37): [True: 14.8k, False: 358k]
  |  Branch (3959:59): [True: 1.12k, False: 13.7k]
  ------------------
 3960|   219k|      return (int) i + 1;
 3961|   211M|  }
 3962|  9.73k|  return 0;
 3963|   232k|}
mg_http_get_header:
 3964|   660k|struct mg_str *mg_http_get_header(struct mg_http_message *h, const char *name) {
 3965|   660k|  size_t i, n = strlen(name), max = sizeof(h->headers) / sizeof(h->headers[0]);
 3966|   807k|  for (i = 0; i < max && h->headers[i].name.len > 0; i++) {
  ------------------
  |  Branch (3966:15): [True: 806k, False: 1.55k]
  |  Branch (3966:26): [True: 162k, False: 643k]
  ------------------
 3967|   162k|    struct mg_str *k = &h->headers[i].name, *v = &h->headers[i].value;
 3968|   162k|    if (n == k->len && mg_ncasecmp(k->buf, name, n) == 0) return v;
  ------------------
  |  Branch (3968:9): [True: 20.5k, False: 142k]
  |  Branch (3968:24): [True: 15.6k, False: 4.95k]
  ------------------
 3969|   162k|  }
 3970|   645k|  return NULL;
 3971|   660k|}
mg_http_parse:
 4036|   232k|int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
 4037|   232k|  int is_response, req_len = mg_http_get_request_len((unsigned char *) s, len);
 4038|   232k|  const char *end = s == NULL ? NULL : s + req_len, *qs;  // Cannot add to NULL
  ------------------
  |  Branch (4038:21): [True: 5.57k, False: 227k]
  ------------------
 4039|   232k|  const struct mg_str *cl;
 4040|   232k|  size_t n;
 4041|   232k|  bool version_prefix_valid;
 4042|       |
 4043|   232k|  memset(hm, 0, sizeof(*hm));
 4044|   232k|  if (req_len <= 0) return req_len;
  ------------------
  |  Branch (4044:7): [True: 13.0k, False: 219k]
  ------------------
 4045|       |
 4046|   219k|  hm->message.buf = hm->head.buf = (char *) s;
 4047|   219k|  hm->body.buf = (char *) end;
 4048|   219k|  hm->head.len = (size_t) req_len;
 4049|   219k|  hm->message.len = hm->body.len = (size_t) -1;  // Set body length to infinite
 4050|       |
 4051|       |  // Parse request line
 4052|   219k|  hm->method.buf = (char *) s;
 4053|  14.7M|  while (s < end && (n = clen(s, end)) > 0) s += n, hm->method.len += n;
  ------------------
  |  Branch (4053:10): [True: 14.7M, False: 0]
  |  Branch (4053:21): [True: 14.5M, False: 219k]
  ------------------
 4054|   442k|  while (s < end && s[0] == ' ') s++;  // Skip spaces
  ------------------
  |  Branch (4054:10): [True: 442k, False: 0]
  |  Branch (4054:21): [True: 222k, False: 219k]
  ------------------
 4055|   219k|  hm->uri.buf = (char *) s;
 4056|  18.8M|  while (s < end && (n = clen(s, end)) > 0) s += n, hm->uri.len += n;
  ------------------
  |  Branch (4056:10): [True: 18.8M, False: 0]
  |  Branch (4056:21): [True: 18.6M, False: 219k]
  ------------------
 4057|   421k|  while (s < end && s[0] == ' ') s++;  // Skip spaces
  ------------------
  |  Branch (4057:10): [True: 421k, False: 0]
  |  Branch (4057:21): [True: 201k, False: 219k]
  ------------------
 4058|   219k|  is_response =
 4059|   219k|      hm->method.len > 5 && (mg_ncasecmp(hm->method.buf, "HTTP/", 5) == 0);
  ------------------
  |  Branch (4059:7): [True: 192k, False: 26.9k]
  |  Branch (4059:29): [True: 26.8k, False: 166k]
  ------------------
 4060|   219k|  if ((s = skiptorn(s, end, &hm->proto)) == NULL) return false;
  ------------------
  |  Branch (4060:7): [True: 258, False: 219k]
  ------------------
 4061|       |  // If we're given a version, check that it is HTTP/x.x
 4062|   219k|  version_prefix_valid =
 4063|   219k|      hm->proto.len > 5 && (mg_ncasecmp(hm->proto.buf, "HTTP/", 5) == 0);
  ------------------
  |  Branch (4063:7): [True: 207k, False: 11.9k]
  |  Branch (4063:28): [True: 192k, False: 15.2k]
  ------------------
 4064|   219k|  if (!is_response && !version_prefix_valid)
  ------------------
  |  Branch (4064:7): [True: 192k, False: 26.8k]
  |  Branch (4064:23): [True: 658, False: 192k]
  ------------------
 4065|    658|    return -1;  // no version detected in request
 4066|   218k|  if (!is_response && hm->proto.len > 0 &&
  ------------------
  |  Branch (4066:7): [True: 192k, False: 26.8k]
  |  Branch (4066:23): [True: 192k, False: 0]
  ------------------
 4067|   192k|      (!version_prefix_valid || hm->proto.len != 8 ||
  ------------------
  |  Branch (4067:8): [True: 0, False: 192k]
  |  Branch (4067:33): [True: 68, False: 192k]
  ------------------
 4068|   192k|       (hm->proto.buf[5] < '0' || hm->proto.buf[5] > '9') ||
  ------------------
  |  Branch (4068:9): [True: 17, False: 192k]
  |  Branch (4068:35): [True: 8, False: 192k]
  ------------------
 4069|   192k|       (hm->proto.buf[6] != '.') ||
  ------------------
  |  Branch (4069:8): [True: 6, False: 192k]
  ------------------
 4070|   192k|       (hm->proto.buf[7] < '0' || hm->proto.buf[7] > '9'))) {
  ------------------
  |  Branch (4070:9): [True: 9, False: 192k]
  |  Branch (4070:35): [True: 9, False: 192k]
  ------------------
 4071|    117|    return -1;
 4072|    117|  }
 4073|       |
 4074|       |  // If URI contains '?' character, setup query string
 4075|   218k|  if ((qs = (const char *) memchr(hm->uri.buf, '?', hm->uri.len)) != NULL) {
  ------------------
  |  Branch (4075:7): [True: 1.07k, False: 217k]
  ------------------
 4076|  1.07k|    hm->query.buf = (char *) qs + 1;
 4077|  1.07k|    hm->query.len = (size_t) (&hm->uri.buf[hm->uri.len] - (qs + 1));
 4078|  1.07k|    hm->uri.len = (size_t) (qs - hm->uri.buf);
 4079|  1.07k|  }
 4080|       |
 4081|       |  // Sanity check. Allow protocol/reason to be empty
 4082|       |  // Do this check after hm->method.len and hm->uri.len are finalised
 4083|   218k|  if (hm->method.len == 0 || hm->uri.len == 0) return -1;
  ------------------
  |  Branch (4083:7): [True: 9, False: 218k]
  |  Branch (4083:30): [True: 13, False: 218k]
  ------------------
 4084|       |
 4085|   218k|  if (!mg_http_parse_headers(s, end, hm->headers,
  ------------------
  |  Branch (4085:7): [True: 365, False: 218k]
  ------------------
 4086|   218k|                             sizeof(hm->headers) / sizeof(hm->headers[0])))
 4087|    365|    return -1;  // error when parsing
 4088|   218k|  cl = mg_http_get_header(hm, "Content-Length");
 4089|   218k|  if (cl != NULL && mg_http_get_header(hm, "Transfer-Encoding") != NULL)
  ------------------
  |  Branch (4089:7): [True: 1.87k, False: 216k]
  |  Branch (4089:21): [True: 3, False: 1.86k]
  ------------------
 4090|      3|    return -1; // cannot contain both CL and TE
 4091|   218k|  if (cl != NULL) {
  ------------------
  |  Branch (4091:7): [True: 1.86k, False: 216k]
  ------------------
 4092|  1.86k|    if (mg_to_size_t(*cl, &hm->body.len) == false) return -1;
  ------------------
  |  Branch (4092:9): [True: 204, False: 1.66k]
  ------------------
 4093|  1.66k|    hm->message.len = (size_t) req_len + hm->body.len;
 4094|  1.66k|  }
 4095|       |
 4096|       |  // mg_http_parse() is used to parse both HTTP requests and HTTP
 4097|       |  // responses. If HTTP response does not have Content-Length set, then
 4098|       |  // body is read until socket is closed, i.e. body.len is infinite (~0).
 4099|       |  //
 4100|       |  // For HTTP requests though, if Content-Length is not specified
 4101|       |  // set body length to 0.
 4102|   218k|  if (hm->body.len == (size_t) ~0 && !is_response) {
  ------------------
  |  Branch (4102:7): [True: 216k, False: 1.66k]
  |  Branch (4102:38): [True: 192k, False: 24.5k]
  ------------------
 4103|   192k|    hm->body.len = 0;
 4104|   192k|    hm->message.len = (size_t) req_len;
 4105|   192k|  }
 4106|       |
 4107|       |  // The 204 (No content) responses also have 0 body length
 4108|   218k|  if (hm->body.len == (size_t) ~0 && is_response &&
  ------------------
  |  Branch (4108:7): [True: 24.5k, False: 193k]
  |  Branch (4108:38): [True: 24.5k, False: 0]
  ------------------
 4109|  24.5k|      mg_strcasecmp(hm->uri, mg_str("204")) == 0) {
  ------------------
  |  | 1524|  24.5k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4109:7): [True: 11.1k, False: 13.4k]
  ------------------
 4110|  11.1k|    hm->body.len = 0;
 4111|  11.1k|    hm->message.len = (size_t) req_len;
 4112|  11.1k|  }
 4113|   218k|  if (hm->message.len < (size_t) req_len) return -1;  // Overflow protection
  ------------------
  |  Branch (4113:7): [True: 15, False: 218k]
  ------------------
 4114|       |
 4115|   218k|  return req_len;
 4116|   218k|}
mg_http_reply:
 4216|   210k|                   const char *fmt, ...) {
 4217|   210k|  va_list ap;
 4218|   210k|  size_t len;
 4219|   210k|  mg_printf(c, "HTTP/1.1 %d %s\r\n%sContent-Length:            \r\n\r\n", code,
 4220|   210k|            mg_http_status_code_str(code), headers == NULL ? "" : headers);
  ------------------
  |  Branch (4220:44): [True: 0, False: 210k]
  ------------------
 4221|   210k|  len = c->send.len;
 4222|   210k|  va_start(ap, fmt);
 4223|   210k|  mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &ap);
 4224|   210k|  va_end(ap);
 4225|   210k|  if (c->send.len > 16) {
  ------------------
  |  Branch (4225:7): [True: 210k, False: 0]
  ------------------
 4226|   210k|    size_t n = mg_snprintf((char *) &c->send.buf[len - 15], 11, "%-10lu",
 4227|   210k|                           (unsigned long) (c->send.len - len));
 4228|   210k|    c->send.buf[len - 15 + n] = ' ';  // Change ending 0 to space
 4229|   210k|  }
 4230|       |  c->pfn_data = NULL;  // Response done
 4231|   210k|}
mg_http_serve_file:
 4348|  21.5k|                        const struct mg_http_serve_opts *opts) {
 4349|  21.5k|  char etag[64], tmp[MG_PATH_MAX];
 4350|  21.5k|  struct mg_fs *fs = opts && opts->fs ? opts->fs : &mg_fs_posix;
  ------------------
  |  Branch (4350:22): [True: 21.5k, False: 0]
  |  Branch (4350:30): [True: 0, False: 21.5k]
  ------------------
 4351|  21.5k|  struct mg_fd *fd = NULL;
 4352|  21.5k|  size_t size = 0;
 4353|  21.5k|  time_t mtime = 0;
 4354|  21.5k|  const char *mime_types = opts && opts->mime_types ? opts->mime_types : NULL;
  ------------------
  |  Branch (4354:28): [True: 21.5k, False: 0]
  |  Branch (4354:36): [True: 0, False: 21.5k]
  ------------------
 4355|  21.5k|  const char *hdrs = opts && opts->extra_headers ? opts->extra_headers : "";
  ------------------
  |  Branch (4355:22): [True: 21.5k, False: 0]
  |  Branch (4355:30): [True: 0, False: 21.5k]
  ------------------
 4356|  21.5k|  struct mg_str *inm = NULL;
 4357|  21.5k|  struct mg_str mime = guess_content_type(mg_str(path), mime_types);
  ------------------
  |  | 1524|  21.5k|#define mg_str(s) mg_str_s(s)
  ------------------
 4358|  21.5k|  bool gzip = false;
 4359|       |
 4360|  21.5k|  if (path != NULL) {
  ------------------
  |  Branch (4360:7): [True: 21.5k, False: 0]
  ------------------
 4361|       |    // If a browser sends us "Accept-Encoding: gzip", try to open .gz first
 4362|  21.5k|    struct mg_str *ae = mg_http_get_header(hm, "Accept-Encoding");
 4363|  21.5k|    if (ae != NULL) {
  ------------------
  |  Branch (4363:9): [True: 1.78k, False: 19.7k]
  ------------------
 4364|  1.78k|      if (mg_match(*ae, mg_str("*gzip*"), NULL)) {
  ------------------
  |  | 1524|  1.78k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4364:11): [True: 265, False: 1.51k]
  ------------------
 4365|    265|        mg_snprintf(tmp, sizeof(tmp), "%s.gz", path);
 4366|    265|        fd = mg_fs_open(fs, tmp, MG_FS_READ);
 4367|    265|        if (fd != NULL) gzip = true, path = tmp;
  ------------------
  |  Branch (4367:13): [True: 0, False: 265]
  ------------------
 4368|    265|      }
 4369|  1.78k|    }
 4370|       |    // No luck opening .gz? Open what we've told to open
 4371|  21.5k|    if (fd == NULL) fd = mg_fs_open(fs, path, MG_FS_READ);
  ------------------
  |  Branch (4371:9): [True: 21.5k, False: 0]
  ------------------
 4372|  21.5k|  }
 4373|       |
 4374|       |  // Failed to open, and page404 is configured? Open it, then
 4375|  21.5k|  if (fd == NULL && opts && opts->page404) {
  ------------------
  |  Branch (4375:7): [True: 21.5k, False: 0]
  |  Branch (4375:21): [True: 21.5k, False: 0]
  |  Branch (4375:29): [True: 0, False: 21.5k]
  ------------------
 4376|      0|    fd = mg_fs_open(fs, opts->page404, MG_FS_READ);
 4377|      0|    path = opts->page404;
 4378|      0|    mime = guess_content_type(mg_str(path), mime_types);
  ------------------
  |  | 1524|      0|#define mg_str(s) mg_str_s(s)
  ------------------
 4379|      0|  }
 4380|       |
 4381|  21.5k|  if (fd == NULL || fs->st(path, &size, &mtime) == 0) {
  ------------------
  |  Branch (4381:7): [True: 21.5k, False: 0]
  |  Branch (4381:21): [True: 0, False: 0]
  ------------------
 4382|  21.5k|    mg_http_reply(c, 404, hdrs, "Not found\n");
 4383|  21.5k|    mg_fs_close(fd);
 4384|       |    // NOTE: mg_http_etag() call should go first!
 4385|  21.5k|  } else if (mg_http_etag(etag, sizeof(etag), size, mtime) != NULL &&
  ------------------
  |  Branch (4385:14): [True: 0, False: 0]
  ------------------
 4386|      0|             (inm = mg_http_get_header(hm, "If-None-Match")) != NULL &&
  ------------------
  |  Branch (4386:14): [True: 0, False: 0]
  ------------------
 4387|      0|             mg_strcasecmp(*inm, mg_str(etag)) == 0) {
  ------------------
  |  | 1524|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4387:14): [True: 0, False: 0]
  ------------------
 4388|      0|    mg_fs_close(fd);
 4389|      0|    mg_http_reply(c, 304, hdrs, "");
 4390|      0|  } else {
 4391|      0|    int n, status = 200;
 4392|      0|    char range[100];
 4393|      0|    size_t r1 = 0, r2 = 0, cl = size;
 4394|       |
 4395|       |    // Handle Range header
 4396|      0|    struct mg_str *rh = mg_http_get_header(hm, "Range");
 4397|      0|    range[0] = '\0';
 4398|      0|    if (rh != NULL && (n = getrange(rh, &r1, &r2)) > 0) {
  ------------------
  |  Branch (4398:9): [True: 0, False: 0]
  |  Branch (4398:23): [True: 0, False: 0]
  ------------------
 4399|       |      // If range is specified like "400-", set second limit to content len
 4400|      0|      if (n == 1) r2 = cl - 1;
  ------------------
  |  Branch (4400:11): [True: 0, False: 0]
  ------------------
 4401|      0|      if (r1 > r2 || r2 >= cl) {
  ------------------
  |  Branch (4401:11): [True: 0, False: 0]
  |  Branch (4401:22): [True: 0, False: 0]
  ------------------
 4402|      0|        status = 416;
 4403|      0|        cl = 0;
 4404|      0|        mg_snprintf(range, sizeof(range), "Content-Range: bytes */%lld\r\n",
 4405|      0|                    (int64_t) size);
 4406|      0|      } else {
 4407|      0|        status = 206;
 4408|      0|        cl = r2 - r1 + 1;
 4409|      0|        mg_snprintf(range, sizeof(range),
 4410|      0|                    "Content-Range: bytes %llu-%llu/%llu\r\n", (uint64_t) r1,
 4411|      0|                    (uint64_t) (r1 + cl - 1), (uint64_t) size);
 4412|      0|        fs->sk(fd->fd, r1);
 4413|      0|      }
 4414|      0|    }
 4415|      0|    mg_printf(c,
 4416|      0|              "HTTP/1.1 %d %s\r\n"
 4417|      0|              "Content-Type: %.*s\r\n"
 4418|      0|              "Etag: %s\r\n"
 4419|      0|              "Content-Length: %llu\r\n"
 4420|      0|              "%s%s%s\r\n",
 4421|      0|              status, mg_http_status_code_str(status), (int) mime.len, mime.buf,
 4422|      0|              etag, (uint64_t) cl, gzip ? "Content-Encoding: gzip\r\n" : "",
  ------------------
  |  Branch (4422:36): [True: 0, False: 0]
  ------------------
 4423|      0|              range, hdrs);
 4424|      0|    if (mg_strcasecmp(hm->method, mg_str("HEAD")) == 0 || c->is_closing) {
  ------------------
  |  | 1524|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4424:9): [True: 0, False: 0]
  |  Branch (4424:59): [True: 0, False: 0]
  ------------------
 4425|      0|      c->pfn_data = NULL;  // Response done
 4426|      0|      mg_fs_close(fd);
 4427|      0|    } else {  // start serving static content only if not closing, see #3354
 4428|       |      // Track to-be-sent content length at the end of c->data, aligned
 4429|      0|      size_t *clp = (size_t *) &c->data[(sizeof(c->data) - sizeof(size_t)) /
 4430|      0|                                        sizeof(size_t) * sizeof(size_t)];
 4431|      0|      c->pfn = static_cb;
 4432|      0|      c->pfn_data = fd;
 4433|      0|      *clp = cl;
 4434|      0|    }
 4435|      0|  }
 4436|  21.5k|}
mg_http_serve_dir:
 4571|   214k|                       const struct mg_http_serve_opts *opts) {
 4572|   214k|  char path[MG_PATH_MAX];
 4573|   214k|  struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
  ------------------
  |  Branch (4573:22): [True: 214k, False: 0]
  ------------------
 4574|   214k|  const char *sp = opts->ssi_pattern;
 4575|   214k|  int flags = uri_to_file_status(c, hm, fs, opts->root_dir, path, sizeof(path));
 4576|   214k|  if (flags < 0) {
  ------------------
  |  Branch (4576:7): [True: 10.1k, False: 204k]
  ------------------
 4577|       |    // Do nothing: the response has already been sent by uri_to_file_status()
 4578|   204k|  } else if (flags & MG_FS_DIR) {
  ------------------
  |  Branch (4578:14): [True: 182k, False: 21.5k]
  ------------------
 4579|   182k|    if (opts->enable_dir_listing) {
  ------------------
  |  Branch (4579:9): [True: 0, False: 182k]
  ------------------
 4580|      0|      listdir(c, hm, opts, path);
 4581|   182k|    } else {
 4582|   182k|      mg_http_reply(c, 403, "", "Forbidden\n");
 4583|   182k|    }
 4584|   182k|  } else if (opts->enable_delete &&
  ------------------
  |  Branch (4584:14): [True: 0, False: 21.5k]
  ------------------
 4585|      0|            mg_strcasecmp(hm->method, mg_str("DELETE")) == 0) {
  ------------------
  |  | 1524|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4585:13): [True: 0, False: 0]
  ------------------
 4586|      0|    mg_http_reply(c, flags && fs->rm(path) ? 200 : 404, "", "");
  ------------------
  |  Branch (4586:22): [True: 0, False: 0]
  |  Branch (4586:31): [True: 0, False: 0]
  ------------------
 4587|  21.5k|  } else if (opts->enable_upload &&
  ------------------
  |  Branch (4587:14): [True: 0, False: 21.5k]
  ------------------
 4588|      0|            (mg_strcasecmp(hm->method, mg_str("POST")) == 0 ||
  ------------------
  |  | 1524|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4588:14): [True: 0, False: 0]
  ------------------
 4589|      0|             mg_strcasecmp(hm->method, mg_str("PUT")) == 0)) {
  ------------------
  |  | 1524|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4589:14): [True: 0, False: 0]
  ------------------
 4590|       |    // Small or already fully buffered body. mg_http_serve_upload() handles
 4591|       |    // the same thing without buffering, for big uploads, from MG_EV_HTTP_HDRS
 4592|      0|    void *fd;
 4593|      0|    bool ok = false;
 4594|      0|    fs->rm(path);  // MG_FS_WRITE appends, not truncates: drop any old file
 4595|      0|    if ((fd = fs->op(path, MG_FS_WRITE)) != NULL) {
  ------------------
  |  Branch (4595:9): [True: 0, False: 0]
  ------------------
 4596|      0|      ok = fs->wr(fd, hm->body.buf, hm->body.len) == hm->body.len;
 4597|      0|      fs->cl(fd);
 4598|      0|    }
 4599|      0|    mg_http_reply(c, ok ? 200 : 500, "", "");
  ------------------
  |  Branch (4599:22): [True: 0, False: 0]
  ------------------
 4600|  21.5k|  } else if (flags && sp != NULL && mg_match(mg_str(path), mg_str(sp), NULL)) {
  ------------------
  |  | 1524|      0|#define mg_str(s) mg_str_s(s)
  ------------------
                } else if (flags && sp != NULL && mg_match(mg_str(path), mg_str(sp), NULL)) {
  ------------------
  |  | 1524|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4600:14): [True: 0, False: 21.5k]
  |  Branch (4600:23): [True: 0, False: 0]
  |  Branch (4600:37): [True: 0, False: 0]
  ------------------
 4601|      0|    mg_http_serve_ssi(c, opts->root_dir, path);
 4602|  21.5k|  } else {
 4603|  21.5k|    mg_http_serve_file(c, hm, path, opts);
 4604|  21.5k|  }
 4605|   214k|}
mg_http_status:
 4771|  12.5k|int mg_http_status(const struct mg_http_message *hm) {
 4772|  12.5k|  return atoi(hm->uri.buf);
 4773|  12.5k|}
mg_http_connect:
 5004|  5.57k|                                      mg_event_handler_t fn, void *fn_data) {
 5005|       |  return mg_connect_svc(mgr, url, fn, fn_data, http_cb, NULL);
 5006|  5.57k|}
mg_iobuf_resize:
 5027|  29.7k|bool mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) {
 5028|  29.7k|  bool ok = true;
 5029|  29.7k|  new_size = roundup(new_size, io->align);
 5030|  29.7k|  if (new_size == 0) {
  ------------------
  |  Branch (5030:7): [True: 22.3k, False: 7.41k]
  ------------------
 5031|  22.3k|    mg_bzero(io->buf, io->size);
 5032|  22.3k|    mg_free(io->buf);
 5033|  22.3k|    io->buf = NULL;
 5034|  22.3k|    io->len = io->size = 0;
 5035|  22.3k|  } else if (new_size != io->size) {
  ------------------
  |  Branch (5035:14): [True: 7.41k, False: 0]
  ------------------
 5036|       |    // NOTE(lsm): do not use realloc here. Use mg_calloc/mg_free only
 5037|  7.41k|    void *p = mg_calloc(1, new_size);
 5038|  7.41k|    if (p != NULL) {
  ------------------
  |  Branch (5038:9): [True: 7.41k, False: 0]
  ------------------
 5039|  7.41k|      size_t len = new_size < io->len ? new_size : io->len;
  ------------------
  |  Branch (5039:20): [True: 0, False: 7.41k]
  ------------------
 5040|  7.41k|      if (len > 0 && io->buf != NULL) memmove(p, io->buf, len);
  ------------------
  |  Branch (5040:11): [True: 0, False: 7.41k]
  |  Branch (5040:22): [True: 0, False: 0]
  ------------------
 5041|  7.41k|      mg_bzero(io->buf, io->size);
 5042|  7.41k|      mg_free(io->buf);
 5043|  7.41k|      io->buf = (unsigned char *) p;
 5044|  7.41k|      io->size = new_size;
 5045|  7.41k|      io->len = len;
 5046|  7.41k|    } else {
 5047|      0|      ok = false;
 5048|      0|      MG_ERROR(("%lld->%lld", (uint64_t) io->size, (uint64_t) new_size));
  ------------------
  |  | 1823|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5049|      0|    }
 5050|  7.41k|  }
 5051|  29.7k|  return ok;
 5052|  29.7k|}
mg_iobuf_add:
 5062|  5.57k|                    size_t len) {
 5063|  5.57k|  size_t new_size = roundup(io->len + len, io->align);
 5064|  5.57k|  mg_iobuf_resize(io, new_size);      // Attempt to resize
 5065|  5.57k|  if (new_size != io->size) len = 0;  // Resize failure, append nothing
  ------------------
  |  Branch (5065:7): [True: 0, False: 5.57k]
  ------------------
 5066|  5.57k|  if (ofs < io->len) memmove(io->buf + ofs + len, io->buf + ofs, io->len - ofs);
  ------------------
  |  Branch (5066:7): [True: 0, False: 5.57k]
  ------------------
 5067|  5.57k|  if (buf != NULL) memmove(io->buf + ofs, buf, len);
  ------------------
  |  Branch (5067:7): [True: 5.57k, False: 0]
  ------------------
 5068|  5.57k|  if (ofs > io->len) io->len += ofs - io->len;
  ------------------
  |  Branch (5068:7): [True: 0, False: 5.57k]
  ------------------
 5069|  5.57k|  io->len += len;
 5070|  5.57k|  return len;
 5071|  5.57k|}
mg_iobuf_del:
 5073|  1.60k|size_t mg_iobuf_del(struct mg_iobuf *io, size_t ofs, size_t len) {
 5074|  1.60k|  if (ofs > io->len) ofs = io->len;
  ------------------
  |  Branch (5074:7): [True: 0, False: 1.60k]
  ------------------
 5075|  1.60k|  if (ofs + len > io->len) len = io->len - ofs;
  ------------------
  |  Branch (5075:7): [True: 0, False: 1.60k]
  ------------------
 5076|  1.60k|  if (io->buf) memmove(io->buf + ofs, io->buf + ofs + len, io->len - ofs - len);
  ------------------
  |  Branch (5076:7): [True: 1.60k, False: 0]
  ------------------
 5077|  1.60k|  if (io->buf) mg_bzero(io->buf + io->len - len, len);
  ------------------
  |  Branch (5077:7): [True: 1.60k, False: 0]
  ------------------
 5078|  1.60k|  io->len -= len;
 5079|  1.60k|  return len;
 5080|  1.60k|}
mg_iobuf_free:
 5082|  22.3k|void mg_iobuf_free(struct mg_iobuf *io) {
 5083|  22.3k|  mg_iobuf_resize(io, 0);
 5084|  22.3k|}
mg_json_get:
 5228|  16.7k|int mg_json_get(struct mg_str json, const char *path, int *toklen) {
 5229|  16.7k|  const char *s = json.buf;
 5230|  16.7k|  int len = (int) json.len;
 5231|  16.7k|  enum { S_VALUE, S_KEY, S_COLON, S_COMMA_OR_EOO } expecting = S_VALUE;
 5232|  16.7k|  unsigned char nesting[MG_JSON_MAX_DEPTH];
 5233|  16.7k|  int i = 0;             // Current offset in `s`
 5234|  16.7k|  int j = 0;             // Offset in `s` we're looking for (return value)
 5235|  16.7k|  int depth = 0;         // Current depth (nesting level)
 5236|  16.7k|  int ed = 0;            // Expected depth
 5237|  16.7k|  int pos = 1;           // Current position in `path`
 5238|  16.7k|  int ci = -1, ei = -1;  // Current and expected index in array
 5239|       |
 5240|  16.7k|  if (toklen) *toklen = 0;
  ------------------
  |  Branch (5240:7): [True: 16.7k, False: 0]
  ------------------
 5241|  16.7k|  if (path[0] != '$') return MG_JSON_INVALID;
  ------------------
  |  Branch (5241:7): [True: 0, False: 16.7k]
  ------------------
 5242|       |
 5243|  16.7k|#define MG_CHECKRET(x)                                  \
 5244|  16.7k|  do {                                                  \
 5245|  16.7k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
 5246|  16.7k|      if (toklen) *toklen = i - j + 1;                  \
 5247|  16.7k|      return j;                                         \
 5248|  16.7k|    }                                                   \
 5249|  16.7k|  } while (0)
 5250|       |
 5251|       |// In the ascii table, the distance between `[` and `]` is 2.
 5252|       |// Ditto for `{` and `}`. Hence +2 in the code below.
 5253|  16.7k|#define MG_EOO(x)                                            \
 5254|  16.7k|  do {                                                       \
 5255|  16.7k|    if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND;   \
 5256|  16.7k|    if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
 5257|  16.7k|    depth--;                                                 \
 5258|  16.7k|    MG_CHECKRET(x);                                          \
 5259|  16.7k|  } while (0)
 5260|       |
 5261|  1.14M|  for (i = 0; i < len; i++) {
  ------------------
  |  Branch (5261:15): [True: 1.14M, False: 1.12k]
  ------------------
 5262|  1.14M|    unsigned char c = ((unsigned char *) s)[i];
 5263|  1.14M|    if (c == ' ' || c == '\t' || c == '\n' || c == '\r') continue;
  ------------------
  |  Branch (5263:9): [True: 1.19k, False: 1.14M]
  |  Branch (5263:21): [True: 672, False: 1.14M]
  |  Branch (5263:34): [True: 746, False: 1.14M]
  |  Branch (5263:47): [True: 1.39k, False: 1.14M]
  ------------------
 5264|  1.14M|    switch (expecting) {
  ------------------
  |  Branch (5264:13): [True: 1.14M, False: 0]
  ------------------
 5265|   518k|      case S_VALUE:
  ------------------
  |  Branch (5265:7): [True: 518k, False: 624k]
  ------------------
 5266|       |        // p("V %s [%.*s] %d %d %d %d\n", path, pos, path, depth, ed, ci, ei);
 5267|   518k|        if (depth == ed) j = i;
  ------------------
  |  Branch (5267:13): [True: 43.9k, False: 474k]
  ------------------
 5268|   518k|        if (c == '{') {
  ------------------
  |  Branch (5268:13): [True: 6.65k, False: 511k]
  ------------------
 5269|  6.65k|          if (depth >= (int) sizeof(nesting)) return MG_JSON_TOO_DEEP;
  ------------------
  |  Branch (5269:15): [True: 8, False: 6.64k]
  ------------------
 5270|  6.64k|          if (depth == ed && path[pos] == '.' && ci == ei) {
  ------------------
  |  Branch (5270:15): [True: 1.94k, False: 4.69k]
  |  Branch (5270:30): [True: 302, False: 1.64k]
  |  Branch (5270:50): [True: 302, False: 0]
  ------------------
 5271|       |            // If we start the object, reset array indices
 5272|    302|            ed++, pos++, ci = ei = -1;
 5273|    302|          }
 5274|  6.64k|          nesting[depth++] = c;
 5275|  6.64k|          expecting = S_KEY;
 5276|  6.64k|          break;
 5277|   511k|        } else if (c == '[') {
  ------------------
  |  Branch (5277:20): [True: 86.9k, False: 424k]
  ------------------
 5278|  86.9k|          if (depth >= (int) sizeof(nesting)) return MG_JSON_TOO_DEEP;
  ------------------
  |  Branch (5278:15): [True: 8, False: 86.9k]
  ------------------
 5279|  86.9k|          if (depth == ed && path[pos] == '[' && ei == ci) {
  ------------------
  |  Branch (5279:15): [True: 27.2k, False: 59.7k]
  |  Branch (5279:30): [True: 388, False: 26.8k]
  |  Branch (5279:50): [True: 388, False: 0]
  ------------------
 5280|    388|            ed++, pos++, ci = 0;
 5281|    776|            for (ei = 0; path[pos] != ']' && path[pos] != '\0'; pos++) {
  ------------------
  |  Branch (5281:26): [True: 388, False: 388]
  |  Branch (5281:46): [True: 388, False: 0]
  ------------------
 5282|    388|              ei *= 10;
 5283|    388|              ei += path[pos] - '0';
 5284|    388|            }
 5285|    388|            if (path[pos] != 0) pos++;
  ------------------
  |  Branch (5285:17): [True: 388, False: 0]
  ------------------
 5286|    388|          }
 5287|  86.9k|          nesting[depth++] = c;
 5288|  86.9k|          break;
 5289|   424k|        } else if (c == ']' && depth > 0) {  // Empty array
  ------------------
  |  Branch (5289:20): [True: 45.2k, False: 379k]
  |  Branch (5289:32): [True: 45.2k, False: 27]
  ------------------
 5290|  45.2k|          MG_EOO(']');
  ------------------
  |  | 5254|  45.2k|  do {                                                       \
  |  | 5255|  45.2k|    if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND;   \
  |  |  ------------------
  |  |  |  Branch (5255:9): [True: 4, False: 45.2k]
  |  |  |  Branch (5255:24): [True: 0, False: 4]
  |  |  ------------------
  |  | 5256|  45.2k|    if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
  |  |  ------------------
  |  |  |  Branch (5256:9): [True: 8, False: 45.2k]
  |  |  ------------------
  |  | 5257|  45.2k|    depth--;                                                 \
  |  | 5258|  45.2k|    MG_CHECKRET(x);                                          \
  |  |  ------------------
  |  |  |  | 5244|  45.2k|  do {                                                  \
  |  |  |  | 5245|  45.2k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5245:9): [True: 14.3k, False: 30.8k]
  |  |  |  |  |  Branch (5245:24): [True: 22, False: 14.3k]
  |  |  |  |  |  Branch (5245:45): [True: 22, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 5246|     22|      if (toklen) *toklen = i - j + 1;                  \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5246:11): [True: 22, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 5247|     22|      return j;                                         \
  |  |  |  | 5248|     22|    }                                                   \
  |  |  |  | 5249|  45.2k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5249:12): [Folded, False: 45.2k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 5259|  45.2k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (5259:12): [Folded, False: 45.2k]
  |  |  ------------------
  ------------------
 5291|   379k|        } else if (c == 't' && i + 3 < len && memcmp(&s[i], "true", 4) == 0) {
  ------------------
  |  Branch (5291:20): [True: 34.0k, False: 345k]
  |  Branch (5291:32): [True: 34.0k, False: 22]
  |  Branch (5291:47): [True: 33.9k, False: 77]
  ------------------
 5292|  33.9k|          i += 3;
 5293|   345k|        } else if (c == 'n' && i + 3 < len && memcmp(&s[i], "null", 4) == 0) {
  ------------------
  |  Branch (5293:20): [True: 18.1k, False: 327k]
  |  Branch (5293:32): [True: 18.1k, False: 17]
  |  Branch (5293:47): [True: 18.0k, False: 104]
  ------------------
 5294|  18.0k|          i += 3;
 5295|   327k|        } else if (c == 'f' && i + 4 < len && memcmp(&s[i], "false", 5) == 0) {
  ------------------
  |  Branch (5295:20): [True: 6.36k, False: 321k]
  |  Branch (5295:32): [True: 6.34k, False: 23]
  |  Branch (5295:47): [True: 6.25k, False: 89]
  ------------------
 5296|  6.25k|          i += 4;
 5297|   321k|        } else if (c == '-' || ((c >= '0' && c <= '9'))) {
  ------------------
  |  Branch (5297:20): [True: 148k, False: 173k]
  |  Branch (5297:34): [True: 168k, False: 4.46k]
  |  Branch (5297:46): [True: 158k, False: 10.0k]
  ------------------
 5298|   306k|          int numlen = 0;
 5299|   306k|          mg_atod(&s[i], len - i, &numlen);
 5300|   306k|          i += numlen - 1;
 5301|   306k|        } else if (c == '"') {
  ------------------
  |  Branch (5301:20): [True: 1.77k, False: 12.7k]
  ------------------
 5302|  1.77k|          int n = mg_pass_string(&s[i + 1], len - i - 1);
 5303|  1.77k|          if (n < 0) return n;
  ------------------
  |  Branch (5303:15): [True: 301, False: 1.47k]
  ------------------
 5304|  1.47k|          i += n + 1;
 5305|  12.7k|        } else {
 5306|  12.7k|          return MG_JSON_INVALID;
 5307|  12.7k|        }
 5308|   411k|        MG_CHECKRET('V');
  ------------------
  |  | 5244|   411k|  do {                                                  \
  |  | 5245|   411k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
  |  |  ------------------
  |  |  |  Branch (5245:9): [True: 16.1k, False: 395k]
  |  |  |  Branch (5245:24): [True: 690, False: 15.4k]
  |  |  |  Branch (5245:45): [True: 690, False: 0]
  |  |  ------------------
  |  | 5246|    690|      if (toklen) *toklen = i - j + 1;                  \
  |  |  ------------------
  |  |  |  Branch (5246:11): [True: 690, False: 0]
  |  |  ------------------
  |  | 5247|    690|      return j;                                         \
  |  | 5248|    690|    }                                                   \
  |  | 5249|   411k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (5249:12): [Folded, False: 411k]
  |  |  ------------------
  ------------------
 5309|   411k|        if (depth == ed && ei >= 0) ci++;
  ------------------
  |  Branch (5309:13): [True: 15.4k, False: 395k]
  |  Branch (5309:28): [True: 0, False: 15.4k]
  ------------------
 5310|   411k|        expecting = S_COMMA_OR_EOO;
 5311|   411k|        break;
 5312|       |
 5313|  87.7k|      case S_KEY:
  ------------------
  |  Branch (5313:7): [True: 87.7k, False: 1.05M]
  ------------------
 5314|  87.7k|        if (c == '"') {
  ------------------
  |  Branch (5314:13): [True: 83.5k, False: 4.13k]
  ------------------
 5315|  83.5k|          int n = mg_pass_string(&s[i + 1], len - i - 1);
 5316|  83.5k|          if (n < 0) return n;
  ------------------
  |  Branch (5316:15): [True: 225, False: 83.3k]
  ------------------
 5317|  83.3k|          if (i + 1 + n >= len) return MG_JSON_NOT_FOUND;
  ------------------
  |  Branch (5317:15): [True: 0, False: 83.3k]
  ------------------
 5318|  83.3k|          if (depth < ed) return MG_JSON_NOT_FOUND;
  ------------------
  |  Branch (5318:15): [True: 1, False: 83.3k]
  ------------------
 5319|  83.3k|          if (depth == ed && path[pos - 1] != '.') return MG_JSON_NOT_FOUND;
  ------------------
  |  Branch (5319:15): [True: 27.0k, False: 56.3k]
  |  Branch (5319:30): [True: 2, False: 27.0k]
  ------------------
 5320|       |          // printf("K %s [%.*s] [%.*s] %d %d %d %d %d\n", path, pos, path, n,
 5321|       |          //        &s[i + 1], n, depth, ed, ci, ei);
 5322|       |          //  NOTE(cpq): in the check sequence below is important.
 5323|       |          //  strncmp() must go first: it fails fast if the remaining length
 5324|       |          //  of the path is smaller than `n`.
 5325|  83.3k|          if (depth == ed && path[pos - 1] == '.' &&
  ------------------
  |  Branch (5325:15): [True: 27.0k, False: 56.3k]
  |  Branch (5325:30): [True: 27.0k, False: 0]
  ------------------
 5326|  27.0k|              strncmp(&s[i + 1], &path[pos], (size_t) n) == 0 &&
  ------------------
  |  Branch (5326:15): [True: 1.86k, False: 25.1k]
  ------------------
 5327|  1.86k|              (path[pos + n] == '\0' || path[pos + n] == '.' ||
  ------------------
  |  Branch (5327:16): [True: 2, False: 1.86k]
  |  Branch (5327:41): [True: 8, False: 1.85k]
  ------------------
 5328|  1.85k|               path[pos + n] == '[')) {
  ------------------
  |  Branch (5328:16): [True: 0, False: 1.85k]
  ------------------
 5329|     10|            pos += n;
 5330|     10|          }
 5331|  83.3k|          i += n + 1;
 5332|  83.3k|          expecting = S_COLON;
 5333|  83.3k|        } else if (c == '}') {  // Empty object
  ------------------
  |  Branch (5333:20): [True: 4.03k, False: 98]
  ------------------
 5334|  4.03k|          MG_EOO('}');
  ------------------
  |  | 5254|  4.03k|  do {                                                       \
  |  | 5255|  4.03k|    if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND;   \
  |  |  ------------------
  |  |  |  Branch (5255:9): [True: 16, False: 4.02k]
  |  |  |  Branch (5255:24): [True: 0, False: 16]
  |  |  ------------------
  |  | 5256|  4.03k|    if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
  |  |  ------------------
  |  |  |  Branch (5256:9): [True: 0, False: 4.03k]
  |  |  ------------------
  |  | 5257|  4.03k|    depth--;                                                 \
  |  | 5258|  4.03k|    MG_CHECKRET(x);                                          \
  |  |  ------------------
  |  |  |  | 5244|  4.03k|  do {                                                  \
  |  |  |  | 5245|  4.03k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5245:9): [True: 1.03k, False: 3.00k]
  |  |  |  |  |  Branch (5245:24): [True: 22, False: 1.00k]
  |  |  |  |  |  Branch (5245:45): [True: 22, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 5246|     22|      if (toklen) *toklen = i - j + 1;                  \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5246:11): [True: 22, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 5247|     22|      return j;                                         \
  |  |  |  | 5248|     22|    }                                                   \
  |  |  |  | 5249|  4.03k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5249:12): [Folded, False: 4.01k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 5259|  4.03k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (5259:12): [Folded, False: 4.01k]
  |  |  ------------------
  ------------------
 5335|  4.01k|          expecting = S_COMMA_OR_EOO;
 5336|  4.01k|          if (depth == ed && ei >= 0) ci++;
  ------------------
  |  Branch (5336:15): [True: 1.00k, False: 3.00k]
  |  Branch (5336:30): [True: 0, False: 1.00k]
  ------------------
 5337|  4.01k|        } else {
 5338|     98|          return MG_JSON_INVALID;
 5339|     98|        }
 5340|  87.3k|        break;
 5341|       |
 5342|  87.3k|      case S_COLON:
  ------------------
  |  Branch (5342:7): [True: 83.2k, False: 1.05M]
  ------------------
 5343|  83.2k|        if (c == ':') {
  ------------------
  |  Branch (5343:13): [True: 83.0k, False: 211]
  ------------------
 5344|  83.0k|          expecting = S_VALUE;
 5345|  83.0k|        } else {
 5346|    211|          return MG_JSON_INVALID;
 5347|    211|        }
 5348|  83.0k|        break;
 5349|       |
 5350|   453k|      case S_COMMA_OR_EOO:
  ------------------
  |  Branch (5350:7): [True: 453k, False: 689k]
  ------------------
 5351|   453k|        if (depth <= 0) {
  ------------------
  |  Branch (5351:13): [True: 893, False: 452k]
  ------------------
 5352|    893|          return MG_JSON_INVALID;
 5353|   452k|        } else if (c == ',') {
  ------------------
  |  Branch (5353:20): [True: 413k, False: 39.3k]
  ------------------
 5354|   413k|          expecting = (nesting[depth - 1] == '{') ? S_KEY : S_VALUE;
  ------------------
  |  Branch (5354:23): [True: 81.1k, False: 332k]
  ------------------
 5355|   413k|        } else if (c == ']' || c == '}') {
  ------------------
  |  Branch (5355:20): [True: 38.0k, False: 1.32k]
  |  Branch (5355:32): [True: 1.06k, False: 257]
  ------------------
 5356|  39.1k|          if (depth == ed && c == '}' && path[pos - 1] == '.')
  ------------------
  |  Branch (5356:15): [True: 12, False: 39.0k]
  |  Branch (5356:30): [True: 8, False: 4]
  |  Branch (5356:42): [True: 7, False: 1]
  ------------------
 5357|      7|            return MG_JSON_NOT_FOUND;
 5358|  39.1k|          if (depth == ed && c == ']' && path[pos - 1] == ',')
  ------------------
  |  Branch (5358:15): [True: 5, False: 39.0k]
  |  Branch (5358:30): [True: 4, False: 1]
  |  Branch (5358:42): [True: 0, False: 4]
  ------------------
 5359|      0|            return MG_JSON_NOT_FOUND;
 5360|  39.1k|          MG_EOO('O');
  ------------------
  |  | 5254|  39.1k|  do {                                                       \
  |  | 5255|  39.1k|    if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND;   \
  |  |  ------------------
  |  |  |  Branch (5255:9): [True: 5, False: 39.0k]
  |  |  |  Branch (5255:24): [True: 0, False: 5]
  |  |  ------------------
  |  | 5256|  39.1k|    if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
  |  |  ------------------
  |  |  |  Branch (5256:9): [True: 22, False: 39.0k]
  |  |  ------------------
  |  | 5257|  39.1k|    depth--;                                                 \
  |  | 5258|  39.0k|    MG_CHECKRET(x);                                          \
  |  |  ------------------
  |  |  |  | 5244|  39.0k|  do {                                                  \
  |  |  |  | 5245|  39.0k|    if (depth == ed && path[pos] == '\0' && ci == ei) { \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5245:9): [True: 11.5k, False: 27.5k]
  |  |  |  |  |  Branch (5245:24): [True: 42, False: 11.5k]
  |  |  |  |  |  Branch (5245:45): [True: 42, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 5246|     42|      if (toklen) *toklen = i - j + 1;                  \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5246:11): [True: 42, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 5247|     42|      return j;                                         \
  |  |  |  | 5248|     42|    }                                                   \
  |  |  |  | 5249|  39.0k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (5249:12): [Folded, False: 39.0k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 5259|  39.0k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (5259:12): [Folded, False: 39.0k]
  |  |  ------------------
  ------------------
 5361|  39.0k|          if (depth == ed && ei >= 0) ci++;
  ------------------
  |  Branch (5361:15): [True: 11.5k, False: 27.5k]
  |  Branch (5361:30): [True: 0, False: 11.5k]
  ------------------
 5362|  39.0k|        } else {
 5363|    257|          return MG_JSON_INVALID;
 5364|    257|        }
 5365|   452k|        break;
 5366|  1.14M|    }
 5367|  1.14M|  }
 5368|  1.12k|  return MG_JSON_NOT_FOUND;
 5369|  16.7k|}
_Z10mg_l2_initP11mg_tcpip_if:
 5716|  5.57k|void mg_l2_init(struct mg_tcpip_if *ifp) {
 5717|  5.57k|  l2_init[ifp->l2type](ifp);
 5718|  5.57k|}
_Z10mg_l2_pollP11mg_tcpip_ifb:
 5720|  5.57k|bool mg_l2_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) {
 5721|  5.57k|  return l2_poll[ifp->l2type](ifp, expired_1000ms);
 5722|  5.57k|}
_Z12mg_l2_headerP11mg_tcpip_if10mg_l2protoPhS2_S2_:
 5725|  5.57k|                      uint8_t *src, uint8_t *dst, uint8_t *frame) {
 5726|  5.57k|  return l2_header[ifp->l2type](ifp, proto, (struct mg_l2addr *) src,
 5727|  5.57k|                                (struct mg_l2addr *) dst, frame);
 5728|  5.57k|}
_Z13mg_l2_trailerP11mg_tcpip_ifmPh:
 5730|  5.57k|size_t mg_l2_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *frame) {
 5731|  5.57k|  return l2_trailer[ifp->l2type](ifp, len, frame);
 5732|  5.57k|}
_Z8mg_l2_rxP11mg_tcpip_ifP10mg_l2protoP6mg_strS4_:
 5735|  5.57k|              struct mg_str *pay, struct mg_str *raw) {
 5736|  5.57k|  return l2_rx[ifp->l2type](ifp, proto, pay, raw);
 5737|  5.57k|}
_Z19mg_l2_driver_outputP11mg_tcpip_ifm:
 5765|  1.17k|size_t mg_l2_driver_output(struct mg_tcpip_if *ifp, size_t len) {
 5766|  1.17k|  size_t n = ifp->driver->tx(ifp->tx.buf, len, ifp);
 5767|  1.17k|  if (n == len) ifp->nsent++;
  ------------------
  |  Branch (5767:7): [True: 1.17k, False: 0]
  ------------------
 5768|  1.17k|  return n;
 5769|  1.17k|}
_Z14mg_l2_eth_initP11mg_tcpip_if:
 5818|  3.71k|void mg_l2_eth_init(struct mg_tcpip_if *ifp) {
 5819|  3.71k|  struct mg_l2addr *l2addr = (struct mg_l2addr *) ifp->mac;
 5820|       |  // If MAC is not set, make a random one
 5821|  3.71k|  if (l2addr->addr.mac[0] == 0 && l2addr->addr.mac[1] == 0 &&
  ------------------
  |  Branch (5821:7): [True: 3.71k, False: 0]
  |  Branch (5821:35): [True: 3.71k, False: 0]
  ------------------
 5822|  3.71k|      l2addr->addr.mac[2] == 0 && l2addr->addr.mac[3] == 0 &&
  ------------------
  |  Branch (5822:7): [True: 3.71k, False: 0]
  |  Branch (5822:35): [True: 3.71k, False: 0]
  ------------------
 5823|  3.71k|      l2addr->addr.mac[4] == 0 && l2addr->addr.mac[5] == 0) {
  ------------------
  |  Branch (5823:7): [True: 3.71k, False: 0]
  |  Branch (5823:35): [True: 3.71k, False: 0]
  ------------------
 5824|  3.71k|    l2addr->addr.mac[0] = 0x02;  // Locally administered, unicast
 5825|  3.71k|    mg_random(&l2addr->addr.mac[1], sizeof(l2addr->addr.mac) - 1);
 5826|  3.71k|    MG_INFO(
  ------------------
  |  | 1824|  3.71k|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1813|  3.71k|  do {                      \
  |  |  |  | 1814|  3.71k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 3.71k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  3.71k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 3.71k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5827|  3.71k|        ("MAC not set. Generated random: %M", mg_print_mac, l2addr->addr.mac));
 5828|  3.71k|  }
 5829|  3.71k|  ifp->l2mtu = 1500;
 5830|  3.71k|  ifp->framesize = 1540;
 5831|  3.71k|}
_Z14mg_l2_eth_pollP11mg_tcpip_ifb:
 5833|  1.85k|bool mg_l2_eth_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) {
 5834|  1.85k|  (void) ifp;
 5835|  1.85k|  (void) expired_1000ms;
 5836|  1.85k|  return true;
 5837|  1.85k|}
_Z16mg_l2_eth_headerP11mg_tcpip_if10mg_l2protoP9mg_l2addrS3_Ph:
 5841|  3.72k|                          uint8_t *frame) {
 5842|  3.72k|  struct eth_data *d = &ifp->l2data.eth;
 5843|  3.72k|  struct eth *eth = (struct eth *) frame;
 5844|  3.72k|  uint8_t *hlp;
 5845|  3.72k|  hlp = (uint8_t *) (eth + 1);
 5846|  3.72k|  memcpy(eth->src, src->addr.mac, sizeof(eth->dst));
 5847|  3.72k|  memcpy(eth->dst, dst->addr.mac, sizeof(eth->dst));
 5848|  3.72k|  if (d->vlan_id == 0) {  // Traditional plain frame
  ------------------
  |  Branch (5848:7): [True: 2.92k, False: 798]
  ------------------
 5849|  2.92k|    eth->type = mg_htons(eth_types[(unsigned int) proto]);
  ------------------
  |  | 2094|  2.92k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 5850|  2.92k|  } else {  // Add 802.1Q tag
 5851|    798|    struct qtag *qtag = (struct qtag *) &eth->type;
 5852|    798|    qtag->tpid = mg_htons(0x8100);
  ------------------
  |  | 2094|    798|#define mg_htons(x) mg_ntohs(x)
  ------------------
 5853|    798|    qtag->tci = mg_htons(d->vlan_id);  // PCP = default (best-effort)
  ------------------
  |  | 2094|    798|#define mg_htons(x) mg_ntohs(x)
  ------------------
 5854|    798|    hlp += sizeof(*qtag);
 5855|    798|    MG_STORE_BE16(qtag + 1, eth_types[(unsigned int) proto]);
  ------------------
  |  | 2060|    798|  do {                                    \
  |  | 2061|    798|    MG_U8P(p)[0] = (uint8_t) ((n) >> 8U); \
  |  |  ------------------
  |  |  |  | 2033|    798|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2062|    798|    MG_U8P(p)[1] = (uint8_t) (n);         \
  |  |  ------------------
  |  |  |  | 2033|    798|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2063|    798|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2063:12): [Folded, False: 798]
  |  |  ------------------
  ------------------
 5856|    798|  }
 5857|  3.72k|  return hlp;
 5858|  3.72k|}
_Z17mg_l2_eth_trailerP11mg_tcpip_ifmPh:
 5860|  3.72k|size_t mg_l2_eth_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) {
 5861|  3.72k|  struct eth_data *d = &ifp->l2data.eth;
 5862|       |  // there is no len field in Ethernet, CRC is hw-calculated; pad to 64 - CRC
 5863|  3.72k|  size_t ethlen =
 5864|  3.72k|      len + sizeof(struct eth) + (d->vlan_id != 0 ? sizeof(struct qtag) : 0);
  ------------------
  |  Branch (5864:35): [True: 798, False: 2.92k]
  ------------------
 5865|  3.72k|  (void) cur;
 5866|  3.72k|  return ethlen >= 60 ? ethlen : 60;
  ------------------
  |  Branch (5866:10): [True: 2.12k, False: 1.59k]
  ------------------
 5867|  3.72k|}
_Z12mg_l2_eth_rxP11mg_tcpip_ifP10mg_l2protoP6mg_strS4_:
 5880|  3.71k|                  struct mg_str *pay, struct mg_str *raw) {
 5881|  3.71k|  struct eth *eth = (struct eth *) raw->buf;
 5882|  3.71k|  struct eth_data *d = &ifp->l2data.eth;
 5883|  3.71k|  uint16_t type, len;
 5884|  3.71k|  unsigned int i;
 5885|  3.71k|  size_t hdrlen =
 5886|  3.71k|      sizeof(struct eth) + (d->vlan_id != 0 ? sizeof(struct qtag) : 0);
  ------------------
  |  Branch (5886:29): [True: 798, False: 2.92k]
  ------------------
 5887|  3.71k|  if (raw->len < hdrlen) return false;  // Truncated - runt?
  ------------------
  |  Branch (5887:7): [True: 1.05k, False: 2.66k]
  ------------------
 5888|  2.66k|  len = (uint16_t) raw->len;
 5889|  2.66k|  if (d->vlan_id == 0) {  // We don't handle VLANs
  ------------------
  |  Branch (5889:7): [True: 1.93k, False: 738]
  ------------------
 5890|  1.93k|    type = mg_ntohs(eth->type);
 5891|  1.93k|  } else {  // We do, check 802.1Q tag
 5892|    738|    struct qtag *qtag = (struct qtag *) &eth->type;
 5893|    738|    if (qtag->tpid != mg_htons(0x8100)) return false;  // Untagged frame
  ------------------
  |  | 2094|    738|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (5893:9): [True: 254, False: 484]
  ------------------
 5894|    484|    if (VLAN_ID(mg_ntohs(qtag->tci)) != VLAN_ID(d->vlan_id))
  ------------------
  |  | 5800|    484|#define VLAN_ID(x) ((uint16_t) ((x) &0x0FFF))
  ------------------
                  if (VLAN_ID(mg_ntohs(qtag->tci)) != VLAN_ID(d->vlan_id))
  ------------------
  |  | 5800|    484|#define VLAN_ID(x) ((uint16_t) ((x) &0x0FFF))
  ------------------
  |  Branch (5894:9): [True: 242, False: 242]
  ------------------
 5895|    242|      return false;  // Not our VLAN
 5896|    242|    type = MG_LOAD_BE16(qtag + 1);
  ------------------
  |  | 2040|    242|  ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 2033|    242|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  |                 ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 2033|    242|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  ------------------
 5897|    242|  }
 5898|  2.17k|  if (ifp->enable_mac_check &&
  ------------------
  |  Branch (5898:7): [True: 0, False: 2.17k]
  ------------------
 5899|      0|      memcmp(eth->dst, ifp->mac, sizeof(eth->dst)) != 0 &&
  ------------------
  |  Branch (5899:7): [True: 0, False: 0]
  ------------------
 5900|      0|      memcmp(eth->dst, mg_l2_eth_mapip(MG_TCPIP_L2ADDR_BCAST, NULL),
  ------------------
  |  Branch (5900:7): [True: 0, False: 0]
  ------------------
 5901|      0|             sizeof(eth->dst)) != 0)
 5902|      0|    return false;  // TODO(): add multicast addresses
 5903|  2.17k|  if (ifp->enable_fcs_check && len > hdrlen + 4) {
  ------------------
  |  Branch (5903:7): [True: 0, False: 2.17k]
  |  Branch (5903:32): [True: 0, False: 0]
  ------------------
 5904|      0|    uint32_t crc, crc_rx;
 5905|      0|    len -= 4;
 5906|      0|    crc = mg_crc32(0, (const char *) raw->buf, len);
 5907|      0|    crc_rx = MG_LOAD_LE32(raw->buf + len);
  ------------------
  |  | 5875|      0|  ((uint32_t) (((uint32_t) MG_U8P(p)[3] << 24U) | \
  |  |  ------------------
  |  |  |  | 2033|      0|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 5876|      0|               ((uint32_t) MG_U8P(p)[2] << 16U) | \
  |  |  ------------------
  |  |  |  | 2033|      0|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 5877|      0|               ((uint32_t) MG_U8P(p)[1] << 8U) | MG_U8P(p)[0]))
  |  |  ------------------
  |  |  |  | 2033|      0|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  |                              ((uint32_t) MG_U8P(p)[1] << 8U) | MG_U8P(p)[0]))
  |  |  ------------------
  |  |  |  | 2033|      0|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  ------------------
 5908|      0|    if (crc_rx != crc)
  ------------------
  |  Branch (5908:9): [True: 0, False: 0]
  ------------------
 5909|      0|      return false;
 5910|      0|  }
 5911|  2.17k|  pay->buf = ((char *) eth) + hdrlen;
 5912|  2.17k|  pay->len = len - hdrlen;
 5913|  2.17k|  if (len > ifp->framesize) return false;  // Oversized
  ------------------
  |  Branch (5913:7): [True: 439, False: 1.73k]
  ------------------
 5914|  9.84k|  for (i = 0; i < sizeof(eth_types) / sizeof(uint16_t); i++) {
  ------------------
  |  Branch (5914:15): [True: 8.27k, False: 1.57k]
  ------------------
 5915|  8.27k|    if (type == eth_types[i]) break;
  ------------------
  |  Branch (5915:9): [True: 162, False: 8.10k]
  ------------------
 5916|  8.27k|  }
 5917|  1.73k|  if (i == sizeof(eth_types) / sizeof(eth_types[0])) {
  ------------------
  |  Branch (5917:7): [True: 1.57k, False: 162]
  ------------------
 5918|  1.57k|    MG_DEBUG(("Unknown eth type %x", type));
  ------------------
  |  | 1825|  1.57k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|  1.57k|  do {                      \
  |  |  |  | 1814|  1.57k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 1.57k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  1.57k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 1.57k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5919|  1.57k|    if (mg_log_level >= MG_LL_VERBOSE)
  ------------------
  |  Branch (5919:9): [True: 0, False: 1.57k]
  ------------------
 5920|      0|      mg_hexdump(raw->buf, raw->len >= 32 ? 32 : raw->len);
  ------------------
  |  Branch (5920:28): [True: 0, False: 0]
  ------------------
 5921|  1.57k|    return false;
 5922|  1.57k|  }
 5923|    162|  *proto = (enum mg_l2proto) i;
 5924|    162|  return true;
 5925|  1.73k|}
_Z14mg_l2_ppp_initP11mg_tcpip_if:
 6099|  1.85k|void mg_l2_ppp_init(struct mg_tcpip_if *ifp) {
 6100|  1.85k|  ifp->l2mtu = 1500;
 6101|  1.85k|  ifp->framesize = ifp->l2mtu + sizeof(struct ppp) + sizeof(struct hdlc_) + 2;
 6102|  1.85k|}
_Z16mg_l2_pppoe_initP11mg_tcpip_if:
 6106|  1.85k|void mg_l2_pppoe_init(struct mg_tcpip_if *ifp) {
 6107|  1.85k|  mg_l2_eth_init(ifp);
 6108|  1.85k|  ifp->l2mtu = ifp->l2mtu - (uint16_t) (sizeof(struct pppoe) +
 6109|  1.85k|                                    sizeof(struct ppp));  // 1500 --> 1492
 6110|  1.85k|}
_Z14mg_l2_ppp_pollP11mg_tcpip_ifb:
 6112|  3.71k|bool mg_l2_ppp_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) {
 6113|  3.71k|  if (expired_1000ms && ifp->state == MG_TCPIP_STATE_DOWN) s_lcpup = false;
  ------------------
  |  | 4735|  3.71k|#define MG_TCPIP_STATE_DOWN 0       // Physical link is down
  ------------------
  |  Branch (6113:7): [True: 3.71k, False: 0]
  |  Branch (6113:25): [True: 0, False: 3.71k]
  ------------------
 6114|  3.71k|  return s_lcpup;
 6115|  3.71k|}
_Z16mg_l2_ppp_headerP11mg_tcpip_if10mg_l2protoP9mg_l2addrS3_Ph:
 6139|  1.85k|                          uint8_t *frame) {
 6140|  1.85k|  (void) ifp;
 6141|  1.85k|  (void) src;
 6142|  1.85k|  (void) dst;
 6143|  1.85k|  return l2_ppp_header(proto, hdlc_header(frame));
 6144|  1.85k|}
_Z18mg_l2_pppoe_headerP11mg_tcpip_if10mg_l2protoP9mg_l2addrS3_Ph:
 6163|  1.85k|                            uint8_t *frame) {
 6164|  1.85k|  (void) dst;
 6165|  1.85k|  return l2_ppp_header(proto, pppoe_header(ifp, MG_TCPIP_L2PROTO_PPPoE_SESS, 0,
 6166|  1.85k|                                           s_id, src, dst, frame));
 6167|  1.85k|}
_Z17mg_l2_ppp_trailerP11mg_tcpip_ifmPh:
 6169|  3.03k|size_t mg_l2_ppp_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) {
 6170|  3.03k|  uint16_t crc;
 6171|  3.03k|  uint8_t *frame;
 6172|  3.03k|  len += sizeof(struct ppp) + sizeof(struct hdlc_);
 6173|  3.03k|  frame = cur - len;
 6174|  3.03k|  crc = mg_crc16(0, (const char *) frame, len);
 6175|  3.03k|  *cur++ = (uint8_t) crc;  // add CRC, note the byte order
 6176|  3.03k|  *cur++ = (uint8_t) (crc >> 8);
 6177|       |  // there is no len field in PPP
 6178|  3.03k|  (void) ifp;
 6179|  3.03k|  return len + 2;
 6180|  3.03k|}
_Z19mg_l2_pppoe_trailerP11mg_tcpip_ifmPh:
 6190|  1.86k|size_t mg_l2_pppoe_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) {
 6191|  1.86k|  return pppoe_trailer(ifp, len + sizeof(struct ppp), cur);
 6192|  1.86k|}
_Z12mg_l2_ppp_rxP11mg_tcpip_ifP10mg_l2protoP6mg_strS4_:
 6456|  1.85k|                  struct mg_str *pay, struct mg_str *raw) {
 6457|  1.85k|  struct hdlc_ *hdlc = (struct hdlc_ *) raw->buf;
 6458|  1.85k|  if (raw->len < sizeof(*hdlc) + 2) return false;  // Truncated
  ------------------
  |  Branch (6458:7): [True: 139, False: 1.72k]
  ------------------
 6459|  1.72k|  if (hdlc->addr == MG_PPP_ADDR && hdlc->ctrl == MG_PPP_CTRL) {
  ------------------
  |  | 6049|  3.44k|#define MG_PPP_ADDR 0xff
  ------------------
                if (hdlc->addr == MG_PPP_ADDR && hdlc->ctrl == MG_PPP_CTRL) {
  ------------------
  |  | 6050|  1.57k|#define MG_PPP_CTRL 0x03
  ------------------
  |  Branch (6459:7): [True: 1.57k, False: 147]
  |  Branch (6459:36): [True: 1.57k, False: 3]
  ------------------
 6460|  1.57k|    pay->buf = (char *) (hdlc + 1);
 6461|  1.57k|    pay->len = raw->len - sizeof(*hdlc) - 2;
 6462|  1.57k|  } else {  // Address-and-Control-Field-Compressed PPP header
 6463|    150|    pay->buf = (char *) raw->buf;
 6464|    150|    pay->len = raw->len - 2;
 6465|    150|  }
 6466|  1.72k|  if (pay->len > ifp->l2mtu + sizeof(struct ppp)) return false;  // Oversized
  ------------------
  |  Branch (6466:7): [True: 339, False: 1.38k]
  ------------------
 6467|  1.38k|  return ppp_rx(ifp, proto, pay, raw);
 6468|  1.72k|}
_Z16mg_l2_pppoe_pollP11mg_tcpip_ifb:
 6522|  1.85k|bool mg_l2_pppoe_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) {
 6523|  1.85k|  if (expired_1000ms && s_state == MG_PPPoE_ST_DISC &&
  ------------------
  |  | 6088|  3.71k|#define MG_PPPoE_ST_DISC 0  // Discovery phase, see what servers are out there
  ------------------
  |  Branch (6523:7): [True: 1.85k, False: 0]
  |  Branch (6523:25): [True: 1.40k, False: 450]
  ------------------
 6524|  1.40k|      ifp->state == MG_TCPIP_STATE_LINK_UP) {
  ------------------
  |  | 4736|  1.40k|#define MG_TCPIP_STATE_LINK_UP 1    // Driver reports physical link is up
  ------------------
  |  Branch (6524:7): [True: 0, False: 1.40k]
  ------------------
 6525|      0|    uint16_t tags[2];
 6526|      0|    tags[0] = mg_htons(0x0101);  // Service Request
  ------------------
  |  | 2094|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6527|      0|    tags[1] = mg_htons(0x0000);  // Any
  ------------------
  |  | 2094|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6528|      0|    pppoe_tx_frame(ifp, MG_PPPoE_PADI, 0, (uint8_t *) tags, sizeof(tags),
  ------------------
  |  | 6082|      0|#define MG_PPPoE_PADI 0x09
  ------------------
 6529|      0|                   mg_l2_eth_mapip(MG_TCPIP_L2ADDR_BCAST, NULL));
 6530|      0|    MG_DEBUG(("Sent PADI"));
  ------------------
  |  | 1825|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6531|  1.85k|  } else if (expired_1000ms && (s_state != MG_PPPoE_ST_SESS ||
  ------------------
  |  | 6090|  3.71k|#define MG_PPPoE_ST_SESS 2  // Session established, PPP traffic is exchanged
  ------------------
  |  Branch (6531:14): [True: 1.85k, False: 0]
  |  Branch (6531:33): [True: 1.42k, False: 432]
  ------------------
 6532|  1.42k|                                ifp->state == MG_TCPIP_STATE_DOWN)) {
  ------------------
  |  | 4735|    432|#define MG_TCPIP_STATE_DOWN 0       // Physical link is down
  ------------------
  |  Branch (6532:33): [True: 0, False: 432]
  ------------------
 6533|  1.42k|    s_state = MG_PPPoE_ST_DISC;
  ------------------
  |  | 6088|  1.42k|#define MG_PPPoE_ST_DISC 0  // Discovery phase, see what servers are out there
  ------------------
 6534|  1.42k|  }
 6535|  1.85k|  return mg_l2_ppp_poll(ifp, expired_1000ms);
 6536|  1.85k|}
_Z14mg_l2_pppoe_rxP11mg_tcpip_ifP10mg_l2protoP6mg_strS4_:
 6543|  1.85k|                    struct mg_str *pay, struct mg_str *raw) {
 6544|  1.85k|  enum mg_l2proto eth_proto;  // raw is handled by eth
 6545|  1.85k|  struct pppoe *pppoe;
 6546|  1.85k|  if (!mg_l2_eth_rx(ifp, &eth_proto, pay, raw)) return false;
  ------------------
  |  Branch (6546:7): [True: 1.79k, False: 66]
  ------------------
 6547|     66|  pppoe = (struct pppoe *) pay->buf;            // here we handle pay, not raw
 6548|     66|  if (pay->len < sizeof(*pppoe)) return false;  // Truncated
  ------------------
  |  Branch (6548:7): [True: 4, False: 62]
  ------------------
 6549|     62|  if (pay->len - sizeof(*pppoe) > ifp->l2mtu + sizeof(struct ppp))
  ------------------
  |  Branch (6549:7): [True: 6, False: 56]
  ------------------
 6550|      6|    return false;  // Oversized
 6551|     56|  if (eth_proto == MG_TCPIP_L2PROTO_PPPoE_DISC) {
  ------------------
  |  Branch (6551:7): [True: 11, False: 45]
  ------------------
 6552|     11|    MG_VERBOSE(("PPPoE_DISC"));
  ------------------
  |  | 1826|     11|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1813|     11|  do {                      \
  |  |  |  | 1814|     11|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 11]
  |  |  |  |  ------------------
  |  |  |  | 1815|     11|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 11]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6553|     11|    if (s_state == MG_PPPoE_ST_DISC && pppoe->code == MG_PPPoE_PADO &&
  ------------------
  |  | 6088|     22|#define MG_PPPoE_ST_DISC 0  // Discovery phase, see what servers are out there
  ------------------
                  if (s_state == MG_PPPoE_ST_DISC && pppoe->code == MG_PPPoE_PADO &&
  ------------------
  |  | 6083|     15|#define MG_PPPoE_PADO 0x07
  ------------------
  |  Branch (6553:9): [True: 4, False: 7]
  |  Branch (6553:40): [True: 0, False: 4]
  ------------------
 6554|      0|        pppoe->id == 0) {
  ------------------
  |  Branch (6554:9): [True: 0, False: 0]
  ------------------
 6555|      0|      uint16_t tags[2];
 6556|      0|      bool has_cookie = false;
 6557|      0|      size_t len = pay->len - sizeof(*pppoe);
 6558|      0|      uint8_t *p = (uint8_t *) (pppoe + 1);
 6559|      0|      uint16_t taglen;
 6560|      0|      while (len >= 4) {  // parse tags for a possible AC-Cookie
  ------------------
  |  Branch (6560:14): [True: 0, False: 0]
  ------------------
 6561|      0|        uint16_t curtag = MG_LOAD_BE16(p);
  ------------------
  |  | 2040|      0|  ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 2033|      0|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  |                 ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 2033|      0|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  ------------------
 6562|      0|        taglen = MG_LOAD_BE16(p + 2);
  ------------------
  |  | 2040|      0|  ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 2033|      0|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  |                 ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 2033|      0|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  ------------------
 6563|      0|        if (taglen > len - 4) return false;  // truncated / malformed
  ------------------
  |  Branch (6563:13): [True: 0, False: 0]
  ------------------
 6564|      0|        if (curtag == 0x0104) {
  ------------------
  |  Branch (6564:13): [True: 0, False: 0]
  ------------------
 6565|      0|          has_cookie = true;
 6566|      0|          break;
 6567|      0|        }
 6568|      0|        len -= 4 + taglen;
 6569|      0|        p += 4 + taglen;
 6570|      0|      }
 6571|      0|      tags[0] = mg_htons(0x0101);  // Service Request
  ------------------
  |  | 2094|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6572|      0|      tags[1] = mg_htons(0x0000);  // Any
  ------------------
  |  | 2094|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6573|      0|      if (has_cookie) {  // copy tags to before AC-Cookie tag in rx buffer
  ------------------
  |  Branch (6573:11): [True: 0, False: 0]
  ------------------
 6574|      0|        memcpy(p -= sizeof(tags), tags, sizeof(tags));  // point to all tags
 6575|      0|        taglen += 4 + sizeof(tags);                     // account for tags
 6576|      0|      } else {
 6577|      0|        p = (uint8_t *) tags;
 6578|      0|        taglen = sizeof(tags);
 6579|      0|      }
 6580|      0|      pppoe_tx_frame(ifp, MG_PPPoE_PADR, 0, p, taglen,
  ------------------
  |  | 6084|      0|#define MG_PPPoE_PADR 0x19
  ------------------
 6581|      0|                     mg_l2_eth_getaddr(ifp, (uint8_t *) raw->buf));
 6582|      0|      MG_DEBUG(("Sent PADR"));
  ------------------
  |  | 1825|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6583|      0|      s_state = MG_PPPoE_ST_REQ;
  ------------------
  |  | 6089|      0|#define MG_PPPoE_ST_REQ 1   // Chose a server, request a session and wait
  ------------------
 6584|     11|    } else if (s_state == MG_PPPoE_ST_REQ && pppoe->code == MG_PPPoE_PADS) {
  ------------------
  |  | 6089|     22|#define MG_PPPoE_ST_REQ 1   // Chose a server, request a session and wait
  ------------------
                  } else if (s_state == MG_PPPoE_ST_REQ && pppoe->code == MG_PPPoE_PADS) {
  ------------------
  |  | 6085|      0|#define MG_PPPoE_PADS 0x65
  ------------------
  |  Branch (6584:16): [True: 0, False: 11]
  |  Branch (6584:46): [True: 0, False: 0]
  ------------------
 6585|      0|      s_id = pppoe->id;
 6586|      0|      memcpy(&ifp->gwmac,
 6587|      0|             mg_l2_eth_getaddr(ifp, (uint8_t *) raw->buf)->addr.mac, 6);
 6588|      0|      MG_DEBUG(("PPPoE session 0x%04x started", mg_ntohs(s_id)));
  ------------------
  |  | 1825|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6589|      0|      s_state = MG_PPPoE_ST_SESS;
  ------------------
  |  | 6090|      0|#define MG_PPPoE_ST_SESS 2  // Session established, PPP traffic is exchanged
  ------------------
 6590|     11|    } else if (s_state == MG_PPPoE_ST_SESS && pppoe->code == MG_PPPoE_PADT &&
  ------------------
  |  | 6090|     22|#define MG_PPPoE_ST_SESS 2  // Session established, PPP traffic is exchanged
  ------------------
                  } else if (s_state == MG_PPPoE_ST_SESS && pppoe->code == MG_PPPoE_PADT &&
  ------------------
  |  | 6086|     18|#define MG_PPPoE_PADT 0xa7
  ------------------
  |  Branch (6590:16): [True: 7, False: 4]
  |  Branch (6590:47): [True: 4, False: 3]
  ------------------
 6591|      4|               pppoe->id == s_id) {
  ------------------
  |  Branch (6591:16): [True: 1, False: 3]
  ------------------
 6592|      1|      MG_ERROR(("Got PADT"));
  ------------------
  |  | 1823|      1|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|      1|  do {                      \
  |  |  |  | 1814|      1|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  |  | 1815|      1|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6593|      1|      s_id = 0;
 6594|      1|      s_lcpup = false;
 6595|      1|      s_state = MG_PPPoE_ST_DISC;
  ------------------
  |  | 6088|      1|#define MG_PPPoE_ST_DISC 0  // Discovery phase, see what servers are out there
  ------------------
 6596|      1|    }
 6597|     45|  } else if (eth_proto == MG_TCPIP_L2PROTO_PPPoE_SESS &&
  ------------------
  |  Branch (6597:14): [True: 7, False: 38]
  ------------------
 6598|      7|             s_state == MG_PPPoE_ST_SESS) {
  ------------------
  |  | 6090|      7|#define MG_PPPoE_ST_SESS 2  // Session established, PPP traffic is exchanged
  ------------------
  |  Branch (6598:14): [True: 5, False: 2]
  ------------------
 6599|      5|    pay->buf = (char *) (pppoe + 1);
 6600|      5|    pay->len = pay->len - sizeof(*pppoe);
 6601|      5|    return ppp_rx(ifp, proto, pay, raw);
 6602|      5|  }
 6603|     51|  return false;
 6604|     56|}
mg_hexdump:
 6956|  2.46k|void mg_hexdump(const void *buf, size_t len) {
 6957|  2.46k|  const unsigned char *p = (const unsigned char *) buf;
 6958|  2.46k|  unsigned char ascii[16], alen = 0;
 6959|  2.46k|  size_t i;
 6960|  36.0k|  for (i = 0; i < len; i++) {
  ------------------
  |  Branch (6960:15): [True: 33.5k, False: 2.46k]
  ------------------
 6961|  33.5k|    if ((i % 16) == 0) {
  ------------------
  |  Branch (6961:9): [True: 2.46k, False: 31.0k]
  ------------------
 6962|       |      // Print buffered ascii chars
 6963|  2.46k|      if (i > 0)
  ------------------
  |  Branch (6963:11): [True: 0, False: 2.46k]
  ------------------
 6964|      0|        logs("  ", 2), logs((char *) ascii, 16), logs("\r\n", 2), alen = 0;
 6965|       |      // Print hex address, then \t
 6966|  2.46k|      logc(nibble((i >> 12) & 15)), logc(nibble((i >> 8) & 15)),
 6967|  2.46k|          logc(nibble((i >> 4) & 15)), logc('0'), logs("   ", 3);
 6968|  2.46k|    }
 6969|  33.5k|    logc(nibble(p[i] >> 4)), logc(nibble(p[i] & 15));  // Two nibbles, e.g. c5
 6970|  33.5k|    logc(' ');                                         // Space after hex number
 6971|  33.5k|    ascii[alen++] = ISPRINT(p[i]) ? p[i] : '.';        // Add to the ascii buf
  ------------------
  |  | 6955|  33.5k|#define ISPRINT(x) ((x) >= ' ' && (x) <= '~')
  |  |  ------------------
  |  |  |  Branch (6955:21): [True: 23.1k, False: 10.4k]
  |  |  |  Branch (6955:35): [True: 16.5k, False: 6.59k]
  |  |  ------------------
  ------------------
 6972|  33.5k|  }
 6973|  8.33k|  while (alen < 16) logs("   ", 3), ascii[alen++] = ' ';
  ------------------
  |  Branch (6973:10): [True: 5.87k, False: 2.46k]
  ------------------
 6974|  2.46k|  logs("  ", 2), logs((char *) ascii, 16), logs("\r\n", 2);
 6975|  2.46k|}
mg_mdash_poll:
 7369|  5.57k|void mg_mdash_poll(struct mg_mgr *mgr) {
 7370|  5.57k|  (void) mgr;
 7371|  5.57k|}
mg_mqtt_next_prop:
 7812|  7.47k|                         size_t ofs) {
 7813|  7.47k|  uint8_t *props = (uint8_t *) msg->dgram.buf + msg->props_start;
 7814|  7.47k|  uint8_t *props_end = props + msg->props_size;
 7815|  7.47k|  uint8_t *i = props + ofs;
 7816|  7.47k|  size_t new_pos = ofs, len;
 7817|       |  
 7818|  7.47k|  if (msg->props_start > msg->dgram.len ||
  ------------------
  |  Branch (7818:7): [True: 0, False: 7.47k]
  ------------------
 7819|  7.47k|    msg->props_size > msg->dgram.len - msg->props_start ||
  ------------------
  |  Branch (7819:5): [True: 0, False: 7.47k]
  ------------------
 7820|  7.47k|    ofs >= msg->props_size)
  ------------------
  |  Branch (7820:5): [True: 1.86k, False: 5.60k]
  ------------------
 7821|  1.86k|  return 0;
 7822|       |
 7823|  5.60k|  memset(prop, 0, sizeof(struct mg_mqtt_prop));
 7824|  5.60k|  prop->id = i[0];
 7825|  5.60k|  i++, new_pos++;
 7826|       |
 7827|  5.60k|  switch (mqtt_prop_type_by_id(prop->id)) {
 7828|     42|    case MQTT_PROP_TYPE_STRING_PAIR:
  ------------------
  |  Branch (7828:5): [True: 42, False: 5.56k]
  ------------------
 7829|     42|      if (i + 2 > props_end) return 0;
  ------------------
  |  Branch (7829:11): [True: 4, False: 38]
  ------------------
 7830|     38|      prop->key.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
 7831|     38|      if (i + 2 + prop->key.len > props_end) return 0;
  ------------------
  |  Branch (7831:11): [True: 28, False: 10]
  ------------------
 7832|     10|      prop->key.buf = (char *) i + 2;
 7833|     10|      i += 2 + prop->key.len;
 7834|     10|      if (i + 2 > props_end) return 0;
  ------------------
  |  Branch (7834:11): [True: 1, False: 9]
  ------------------
 7835|      9|      prop->val.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
 7836|      9|      prop->val.buf = (char *) i + 2;
 7837|      9|      if (i + 2 + prop->val.len > props_end) return 0;
  ------------------
  |  Branch (7837:11): [True: 2, False: 7]
  ------------------
 7838|      7|      new_pos += 2 * sizeof(uint16_t) + prop->val.len + prop->key.len;
 7839|      7|      break;
 7840|  1.21k|    case MQTT_PROP_TYPE_BYTE:
  ------------------
  |  Branch (7840:5): [True: 1.21k, False: 4.39k]
  ------------------
 7841|  1.21k|      if (i + 1 > props_end) return 0;
  ------------------
  |  Branch (7841:11): [True: 11, False: 1.20k]
  ------------------
 7842|  1.20k|      prop->iv = (uint8_t) i[0];
 7843|  1.20k|      new_pos++;
 7844|  1.20k|      break;
 7845|    393|    case MQTT_PROP_TYPE_SHORT:
  ------------------
  |  Branch (7845:5): [True: 393, False: 5.21k]
  ------------------
 7846|    393|      if (i + 2 > props_end) return 0;
  ------------------
  |  Branch (7846:11): [True: 8, False: 385]
  ------------------
 7847|    385|      prop->iv = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
 7848|    385|      new_pos += sizeof(uint16_t);
 7849|    385|      break;
 7850|  3.11k|    case MQTT_PROP_TYPE_INT:
  ------------------
  |  Branch (7850:5): [True: 3.11k, False: 2.49k]
  ------------------
 7851|  3.11k|      if (i + 4 > props_end) return 0;
  ------------------
  |  Branch (7851:11): [True: 7, False: 3.11k]
  ------------------
 7852|  3.11k|      prop->iv = ((uint32_t) i[0] << 24) | ((uint32_t) i[1] << 16) |
 7853|  3.11k|                 ((uint32_t) i[2] << 8) | i[3];
 7854|  3.11k|      new_pos += sizeof(uint32_t);
 7855|  3.11k|      break;
 7856|     52|    case MQTT_PROP_TYPE_STRING:
  ------------------
  |  Branch (7856:5): [True: 52, False: 5.55k]
  ------------------
 7857|     52|      if (i + 2 > props_end) return 0;
  ------------------
  |  Branch (7857:11): [True: 6, False: 46]
  ------------------
 7858|     46|      prop->val.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
 7859|     46|      prop->val.buf = (char *) i + 2;
 7860|     46|      if (i + 2 + prop->val.len > props_end) return 0;
  ------------------
  |  Branch (7860:11): [True: 28, False: 18]
  ------------------
 7861|     18|      new_pos += 2 + prop->val.len;
 7862|     18|      break;
 7863|     57|    case MQTT_PROP_TYPE_BINARY_DATA:
  ------------------
  |  Branch (7863:5): [True: 57, False: 5.55k]
  ------------------
 7864|     57|      if (i + 2 > props_end) return 0;
  ------------------
  |  Branch (7864:11): [True: 5, False: 52]
  ------------------
 7865|     52|      prop->val.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
 7866|     52|      prop->val.buf = (char *) i + 2;
 7867|     52|      if (i + 2 + prop->val.len > props_end) return 0;
  ------------------
  |  Branch (7867:11): [True: 23, False: 29]
  ------------------
 7868|     29|      new_pos += 2 + prop->val.len;
 7869|     29|      break;
 7870|    631|    case MQTT_PROP_TYPE_VARIABLE_INT:
  ------------------
  |  Branch (7870:5): [True: 631, False: 4.97k]
  ------------------
 7871|    631|      len = decode_varint(i, (size_t) (props_end - i), &prop->iv);
 7872|    631|      if (i + len > props_end) return 0;
  ------------------
  |  Branch (7872:11): [True: 0, False: 631]
  ------------------
 7873|    631|      new_pos = (len == 0) ? 0 : new_pos + len;
  ------------------
  |  Branch (7873:17): [True: 9, False: 622]
  ------------------
 7874|    631|      break;
 7875|    102|    default:
  ------------------
  |  Branch (7875:5): [True: 102, False: 5.50k]
  ------------------
 7876|    102|      new_pos = 0;
 7877|    102|      break;
 7878|  5.60k|  }
 7879|       |
 7880|  5.48k|  return new_pos;
 7881|  5.60k|}
mg_mqtt_parse:
 8026|  22.3k|                  struct mg_mqtt_message *m) {
 8027|  22.3k|  uint8_t lc = 0, *p, *end;
 8028|  22.3k|  uint32_t n = 0, len_len = 0, tmp;
 8029|       |
 8030|  22.3k|  memset(m, 0, sizeof(*m));
 8031|  22.3k|  m->dgram.buf = (char *) buf;
 8032|  22.3k|  if (len < 2) return MQTT_INCOMPLETE;
  ------------------
  |  Branch (8032:7): [True: 11.3k, False: 10.9k]
  ------------------
 8033|  10.9k|  m->cmd = (uint8_t) (buf[0] >> 4);
 8034|  10.9k|  m->qos = (buf[0] >> 1) & 3;
 8035|       |
 8036|  10.9k|  n = len_len = 0;
 8037|  10.9k|  p = (uint8_t *) buf + 1;
 8038|  12.9k|  while ((size_t) (p - buf) < len) {
  ------------------
  |  Branch (8038:10): [True: 12.8k, False: 84]
  ------------------
 8039|  12.8k|    lc = *((uint8_t *) p++);
 8040|  12.8k|    n += (uint32_t) ((lc & 0x7f) << 7 * len_len);
 8041|  12.8k|    len_len++;
 8042|  12.8k|    if (!(lc & 0x80)) break;
  ------------------
  |  Branch (8042:9): [True: 10.6k, False: 2.22k]
  ------------------
 8043|  2.22k|    if (len_len >= 4) return MQTT_MALFORMED;
  ------------------
  |  Branch (8043:9): [True: 220, False: 2.00k]
  ------------------
 8044|  2.22k|  }
 8045|  10.7k|  end = p + n;
 8046|  10.7k|  if ((lc & 0x80) || (end > buf + len)) return MQTT_INCOMPLETE;
  ------------------
  |  Branch (8046:7): [True: 84, False: 10.6k]
  |  Branch (8046:22): [True: 5.46k, False: 5.19k]
  ------------------
 8047|  5.19k|  m->dgram.len = (size_t) (end - buf);
 8048|       |
 8049|  5.19k|  switch (m->cmd) {
 8050|    476|    case MQTT_CMD_CONNACK:
  ------------------
  |  | 3546|    476|#define MQTT_CMD_CONNACK 2
  ------------------
  |  Branch (8050:5): [True: 476, False: 4.71k]
  ------------------
 8051|    476|      if (end - p < 2) return MQTT_MALFORMED;
  ------------------
  |  Branch (8051:11): [True: 52, False: 424]
  ------------------
 8052|    424|      m->ack = p[1];
 8053|    424|      p += 2;
 8054|    424|      if (version == 5) {
  ------------------
  |  Branch (8054:11): [True: 212, False: 212]
  ------------------
 8055|    212|        if (p >= end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8055:13): [True: 2, False: 210]
  ------------------
 8056|    210|        len_len = (uint32_t) decode_varint(p, (size_t) (end - p), &tmp);
 8057|    210|        if (!len_len) return MQTT_MALFORMED;
  ------------------
  |  Branch (8057:13): [True: 14, False: 196]
  ------------------
 8058|    196|        m->props_size = (size_t) tmp;
 8059|    196|        m->props_start = (size_t) (p + len_len - buf);
 8060|    196|        p += len_len + m->props_size;
 8061|    196|        if (p > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8061:13): [True: 115, False: 81]
  ------------------
 8062|    196|      }
 8063|    293|      break;
 8064|  1.78k|    case MQTT_CMD_PUBACK:
  ------------------
  |  | 3548|  1.78k|#define MQTT_CMD_PUBACK 4
  ------------------
  |  Branch (8064:5): [True: 1.78k, False: 3.40k]
  ------------------
 8065|  2.30k|    case MQTT_CMD_PUBREC:
  ------------------
  |  | 3549|  2.30k|#define MQTT_CMD_PUBREC 5
  ------------------
  |  Branch (8065:5): [True: 518, False: 4.67k]
  ------------------
 8066|  2.41k|    case MQTT_CMD_PUBREL:
  ------------------
  |  | 3550|  2.41k|#define MQTT_CMD_PUBREL 6
  ------------------
  |  Branch (8066:5): [True: 108, False: 5.08k]
  ------------------
 8067|  2.85k|    case MQTT_CMD_PUBCOMP:
  ------------------
  |  | 3551|  2.85k|#define MQTT_CMD_PUBCOMP 7
  ------------------
  |  Branch (8067:5): [True: 442, False: 4.74k]
  ------------------
 8068|  2.92k|    case MQTT_CMD_SUBSCRIBE:
  ------------------
  |  | 3552|  2.92k|#define MQTT_CMD_SUBSCRIBE 8
  ------------------
  |  Branch (8068:5): [True: 68, False: 5.12k]
  ------------------
 8069|  3.04k|    case MQTT_CMD_SUBACK:
  ------------------
  |  | 3553|  3.04k|#define MQTT_CMD_SUBACK 9
  ------------------
  |  Branch (8069:5): [True: 128, False: 5.06k]
  ------------------
 8070|  3.09k|    case MQTT_CMD_UNSUBSCRIBE:
  ------------------
  |  | 3554|  3.09k|#define MQTT_CMD_UNSUBSCRIBE 10
  ------------------
  |  Branch (8070:5): [True: 42, False: 5.14k]
  ------------------
 8071|  3.10k|    case MQTT_CMD_UNSUBACK:
  ------------------
  |  | 3555|  3.10k|#define MQTT_CMD_UNSUBACK 11
  ------------------
  |  Branch (8071:5): [True: 12, False: 5.17k]
  ------------------
 8072|  3.10k|      if (p + 2 > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8072:11): [True: 282, False: 2.82k]
  ------------------
 8073|  2.82k|      m->id = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
 8074|  2.82k|      p += 2;
 8075|  2.82k|      break;
 8076|    800|    case MQTT_CMD_PUBLISH: {
  ------------------
  |  | 3547|    800|#define MQTT_CMD_PUBLISH 3
  ------------------
  |  Branch (8076:5): [True: 800, False: 4.39k]
  ------------------
 8077|    800|      if (p + 2 > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8077:11): [True: 12, False: 788]
  ------------------
 8078|    788|      m->topic.len = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
 8079|    788|      m->topic.buf = (char *) p + 2;
 8080|    788|      p += 2 + m->topic.len;
 8081|    788|      if (p > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8081:11): [True: 350, False: 438]
  ------------------
 8082|    438|      if (m->qos > 0) {
  ------------------
  |  Branch (8082:11): [True: 112, False: 326]
  ------------------
 8083|    112|        if (p + 2 > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8083:13): [True: 6, False: 106]
  ------------------
 8084|    106|        m->id = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
 8085|    106|        p += 2;
 8086|    106|      }
 8087|    432|      if (p > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8087:11): [True: 0, False: 432]
  ------------------
 8088|    432|      if (version == 5 && p + 2 < end) {
  ------------------
  |  Branch (8088:11): [True: 216, False: 216]
  |  Branch (8088:27): [True: 208, False: 8]
  ------------------
 8089|    208|        len_len = (uint32_t) decode_varint(p, (size_t) (end - p), &tmp);
 8090|    208|        if (!len_len) return MQTT_MALFORMED;
  ------------------
  |  Branch (8090:13): [True: 6, False: 202]
  ------------------
 8091|    202|        m->props_size = (size_t) tmp;
 8092|    202|        m->props_start = (size_t) (p + len_len - buf);
 8093|    202|        p += len_len + m->props_size;
 8094|    202|      }
 8095|    426|      if (p > end) return MQTT_MALFORMED;
  ------------------
  |  Branch (8095:11): [True: 6, False: 420]
  ------------------
 8096|    420|      m->data.buf = (char *) p;
 8097|    420|      m->data.len = (size_t) (end - p);
 8098|    420|      break;
 8099|    426|    }
 8100|    812|    default: break;
  ------------------
  |  Branch (8100:5): [True: 812, False: 4.37k]
  ------------------
 8101|  5.19k|  }
 8102|  4.34k|  return MQTT_OK;
 8103|  5.19k|}
mg_vprintf:
 8242|   214k|size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list *ap) {
 8243|   214k|  size_t old = c->send.len;
 8244|   214k|  size_t expected = mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
 8245|   214k|  size_t actual = c->send.len - old;
 8246|   214k|  if (actual != expected) {
  ------------------
  |  Branch (8246:7): [True: 0, False: 214k]
  ------------------
 8247|      0|    mg_error(c, "OOM");
 8248|      0|    c->send.len = old;
 8249|      0|    actual = 0;
 8250|      0|  }
 8251|   214k|  return actual;
 8252|   214k|}
mg_printf:
 8254|   214k|size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
 8255|   214k|  size_t len = 0;
 8256|   214k|  va_list ap;
 8257|   214k|  va_start(ap, fmt);
 8258|   214k|  len = mg_vprintf(c, fmt, &ap);
 8259|       |  va_end(ap);
 8260|   214k|  return len;
 8261|   214k|}
mg_aton:
 8402|  5.57k|bool mg_aton(struct mg_str str, struct mg_addr *addr) {
 8403|  5.57k|  return mg_atone(str, addr) || mg_atonl(str, addr) || mg_aton_(str, addr);
  ------------------
  |  Branch (8403:10): [True: 0, False: 5.57k]
  |  Branch (8403:33): [True: 5.57k, False: 0]
  |  Branch (8403:56): [True: 0, False: 0]
  ------------------
 8404|  5.57k|}
mg_alloc_conn:
 8406|  5.57k|struct mg_connection *mg_alloc_conn(struct mg_mgr *mgr) {
 8407|  5.57k|  struct mg_connection *c =
 8408|  5.57k|      (struct mg_connection *) mg_calloc(1, sizeof(*c) + mgr->extraconnsize);
 8409|  5.57k|  if (c != NULL) {
  ------------------
  |  Branch (8409:7): [True: 5.57k, False: 0]
  ------------------
 8410|  5.57k|    c->mgr = mgr;
 8411|  5.57k|    c->send.align = c->recv.align = c->rtls.align = MG_IO_SIZE;
  ------------------
  |  |    7|  5.57k|#define MG_IO_SIZE (32 * 1024 * 1024)  // Big IO size for fast resizes
  ------------------
 8412|  5.57k|    c->id = ++mgr->nextid;
 8413|  5.57k|    MG_PROF_INIT(c);
 8414|  5.57k|  }
 8415|  5.57k|  return c;
 8416|  5.57k|}
mg_close_conn:
 8418|  5.57k|void mg_close_conn(struct mg_connection *c) {
 8419|  5.57k|  mg_resolve_cancel(c);  // Close any pending DNS query
 8420|  5.57k|  LIST_DELETE(struct mg_connection, &c->mgr->conns, c);
  ------------------
  |  | 2162|  5.57k|  do {                                     \
  |  | 2163|  5.57k|    type_ **h = head_;                     \
  |  | 2164|  5.57k|    while (*h != (elem_)) h = &(*h)->next; \
  |  |  ------------------
  |  |  |  Branch (2164:12): [True: 0, False: 5.57k]
  |  |  ------------------
  |  | 2165|  5.57k|    *h = (elem_)->next;                    \
  |  | 2166|  5.57k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2166:12): [Folded, False: 5.57k]
  |  |  ------------------
  ------------------
 8421|  5.57k|  if (c == c->mgr->dns4.c) c->mgr->dns4.c = NULL;
  ------------------
  |  Branch (8421:7): [True: 0, False: 5.57k]
  ------------------
 8422|  5.57k|  if (c == c->mgr->dns6.c) c->mgr->dns6.c = NULL;
  ------------------
  |  Branch (8422:7): [True: 0, False: 5.57k]
  ------------------
 8423|       |  // Order of operations is important. `MG_EV_CLOSE` event must be fired
 8424|       |  // before we deallocate received data, see #1331
 8425|  5.57k|  mg_call(c, MG_EV_CLOSE, NULL);
 8426|  5.57k|  MG_DEBUG(("%lu %ld closed", c->id, c->fd));
  ------------------
  |  | 1825|  5.57k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|  5.57k|  do {                      \
  |  |  |  | 1814|  5.57k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  5.57k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8427|  5.57k|  MG_PROF_DUMP(c);
 8428|  5.57k|  MG_PROF_FREE(c);
 8429|       |
 8430|  5.57k|  mg_tls_free(c);
 8431|  5.57k|  mg_iobuf_free(&c->recv);
 8432|  5.57k|  mg_iobuf_free(&c->send);
 8433|  5.57k|  mg_iobuf_free(&c->rtls);
 8434|  5.57k|  mg_bzero((unsigned char *) c, sizeof(*c));
 8435|  5.57k|  mg_free(c);
 8436|  5.57k|}
mg_connect_svc:
 8440|  5.57k|                                     mg_event_handler_t pfn, void *pfn_data) {
 8441|  5.57k|  struct mg_connection *c = NULL;
 8442|  5.57k|  if (url == NULL || url[0] == '\0') {
  ------------------
  |  Branch (8442:7): [True: 0, False: 5.57k]
  |  Branch (8442:22): [True: 0, False: 5.57k]
  ------------------
 8443|      0|    MG_ERROR(("null url"));
  ------------------
  |  | 1823|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8444|      0|#if MG_ENABLE_TCPIP
 8445|  5.57k|  } else if (mgr->ifp != NULL && mgr->ifp->state != MG_TCPIP_STATE_READY) {
  ------------------
  |  | 4740|  5.57k|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
  |  Branch (8445:14): [True: 5.57k, False: 0]
  |  Branch (8445:34): [True: 0, False: 5.57k]
  ------------------
 8446|      0|    MG_ERROR(("Network is down"));
  ------------------
  |  | 1823|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8447|      0|#endif
 8448|  5.57k|  } else if ((c = mg_alloc_conn(mgr)) == NULL) {
  ------------------
  |  Branch (8448:14): [True: 0, False: 5.57k]
  ------------------
 8449|      0|    MG_ERROR(("OOM"));
  ------------------
  |  | 1823|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8450|  5.57k|  } else {
 8451|  5.57k|    LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
  ------------------
  |  | 2149|  5.57k|  do {                                     \
  |  | 2150|  5.57k|    (elem_)->next = (*head_);              \
  |  | 2151|  5.57k|    *(head_) = (elem_);                    \
  |  | 2152|  5.57k|  } while (0)
  |  |  ------------------
  |  |  |  Branch (2152:12): [Folded, False: 5.57k]
  |  |  ------------------
  ------------------
 8452|  5.57k|    c->is_udp = (strncmp(url, "udp:", 4) == 0);
 8453|  5.57k|    c->fd = (void *) (size_t) MG_INVALID_SOCKET;
  ------------------
  |  | 1324|  5.57k|#define MG_INVALID_SOCKET (-1)
  ------------------
 8454|  5.57k|    c->fn = fn;
 8455|  5.57k|    c->is_client = true;
 8456|  5.57k|    c->fn_data = fn_data;
 8457|  5.57k|    c->is_tls = (mg_url_is_ssl(url) != 0);
 8458|  5.57k|    c->pfn = pfn;
 8459|  5.57k|    c->pfn_data = pfn_data;
 8460|  5.57k|    mg_call(c, MG_EV_OPEN, (void *) url);
 8461|  5.57k|    MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
  ------------------
  |  | 1825|  5.57k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|  5.57k|  do {                      \
  |  |  |  | 1814|  5.57k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  5.57k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8462|  5.57k|    mg_resolve(c, url);
 8463|  5.57k|  }
 8464|  5.57k|  return c;
 8465|  5.57k|}
mg_mgr_free:
 8527|  5.57k|void mg_mgr_free(struct mg_mgr *mgr) {
 8528|  5.57k|  struct mg_connection *c;
 8529|  5.57k|  struct mg_timer *tmp, *t = mgr->timers;
 8530|  5.57k|  while (t != NULL) tmp = t->next, mg_free(t), t = tmp;
  ------------------
  |  Branch (8530:10): [True: 0, False: 5.57k]
  ------------------
 8531|  5.57k|  mgr->timers = NULL;  // Important. Next call to poll won't touch timers
 8532|  11.1k|  for (c = mgr->conns; c != NULL; c = c->next) c->is_closing = 1;
  ------------------
  |  Branch (8532:24): [True: 5.57k, False: 5.57k]
  ------------------
 8533|       |#if MG_ENABLE_MDASH
 8534|       |  mg_mdash_free(mgr);  // Before the final poll, so mdash does not reconnect
 8535|       |#endif
 8536|  5.57k|  mg_mgr_poll(mgr, 0);
 8537|       |#if MG_ENABLE_FREERTOS_TCP
 8538|       |  FreeRTOS_DeleteSocketSet(mgr->ss);
 8539|       |#endif
 8540|  5.57k|  MG_DEBUG(("All connections closed"));
  ------------------
  |  | 1825|  5.57k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|  5.57k|  do {                      \
  |  |  |  | 1814|  5.57k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  5.57k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8541|  5.57k|#if MG_ENABLE_EPOLL
 8542|  5.57k|  if (mgr->epoll_fd >= 0) close(mgr->epoll_fd), mgr->epoll_fd = -1;
  ------------------
  |  Branch (8542:7): [True: 5.57k, False: 0]
  ------------------
 8543|  5.57k|#endif
 8544|  5.57k|  mg_tls_ctx_free(mgr);
 8545|  5.57k|#if MG_ENABLE_TCPIP
 8546|  5.57k|  if (mgr->ifp) mg_tcpip_free(mgr->ifp);
  ------------------
  |  Branch (8546:7): [True: 5.57k, False: 0]
  ------------------
 8547|  5.57k|#endif
 8548|  5.57k|}
mg_mgr_init:
 8550|  5.57k|void mg_mgr_init(struct mg_mgr *mgr) {
 8551|  5.57k|  memset(mgr, 0, sizeof(*mgr));
 8552|  5.57k|#if MG_ENABLE_EPOLL
 8553|  5.57k|  if ((mgr->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0)
  ------------------
  |  Branch (8553:7): [True: 0, False: 5.57k]
  ------------------
 8554|  5.57k|    MG_ERROR(("epoll_create1 errno %d", errno));
  ------------------
  |  | 1823|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8555|       |#else
 8556|       |  mgr->epoll_fd = -1;
 8557|       |#endif
 8558|       |#if MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK
 8559|       |  // clang-format off
 8560|       |  { WSADATA data; WSAStartup(MAKEWORD(2, 2), &data); }
 8561|       |  // clang-format on
 8562|       |#elif MG_ENABLE_FREERTOS_TCP
 8563|       |  mgr->ss = FreeRTOS_CreateSocketSet();
 8564|       |#elif MG_ARCH == MG_ARCH_UNIX
 8565|       |  // Ignore SIGPIPE signal, so if client cancels the request, it
 8566|       |  // won't kill the whole process.
 8567|  5.57k|  signal(SIGPIPE, SIG_IGN);
 8568|       |#elif MG_ENABLE_TCPIP_DRIVER_INIT && defined(MG_TCPIP_DRIVER_INIT)
 8569|       |  MG_TCPIP_DRIVER_INIT(mgr);
 8570|       |#endif
 8571|       |#if MG_ENABLE_BSD_SOCKETS
 8572|       |  mgr->pipe.q = NULL;
 8573|       |#else
 8574|  5.57k|  mgr->pipe.fd = MG_INVALID_SOCKET;
  ------------------
  |  | 1324|  5.57k|#define MG_INVALID_SOCKET (-1)
  ------------------
 8575|  5.57k|#endif
 8576|  5.57k|  mgr->dnstimeout = 3000;
 8577|  5.57k|  mgr->dns4.url = "udp://8.8.8.8:53";
 8578|  5.57k|  mgr->dns6.url = "udp://[2001:4860:4860::8888]:53";
 8579|  5.57k|  mg_tls_ctx_init(mgr);
 8580|  5.57k|  MG_DEBUG(("MG_IO_SIZE: %lu, TLS: %s, conn size: %zu, mgr size: %zu",
  ------------------
  |  | 1825|  5.57k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|  5.57k|  do {                      \
  |  |  |  | 1814|  5.57k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 5.57k]
  |  |  |  |  |  Branch (1814:19): [Folded, False: 0]
  |  |  |  |  |  Branch (1814:19): [Folded, False: 0]
  |  |  |  |  |  Branch (1814:19): [Folded, False: 0]
  |  |  |  |  |  Branch (1814:19): [Folded, False: 0]
  |  |  |  |  |  Branch (1814:19): [True: 0, Folded]
  |  |  |  |  ------------------
  |  |  |  | 1815|  5.57k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8581|  5.57k|            MG_IO_SIZE,
 8582|  5.57k|            MG_TLS == MG_TLS_NONE      ? "none"
 8583|  5.57k|            : MG_TLS == MG_TLS_MBED    ? "MbedTLS"
 8584|  5.57k|            : MG_TLS == MG_TLS_OPENSSL ? "OpenSSL"
 8585|  5.57k|            : MG_TLS == MG_TLS_BUILTIN ? "builtin"
 8586|  5.57k|            : MG_TLS == MG_TLS_WOLFSSL ? "WolfSSL"
 8587|  5.57k|                                       : "custom",
 8588|  5.57k|            sizeof(struct mg_connection), sizeof(struct mg_mgr)));
 8589|       |#if MG_ENABLE_MDASH
 8590|       |  mg_mdash_init(mgr);
 8591|       |#endif
 8592|  5.57k|}
mg_tcpip_init:
10858|  5.57k|void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
10859|       |  // If L2 address is not set, make a random one; fill MTU
10860|  5.57k|  mg_l2_init(ifp);
10861|  5.57k|  ifp->mtu = ifp->l2mtu;
10862|  5.57k|  if (MG_ENABLE_TCPIP_TCPRTX) ifp->enable_tcp_retransmit = true;
  ------------------
  |  | 1361|  5.57k|#define MG_ENABLE_TCPIP_TCPRTX 0  // TCP retransmission queue
  |  |  ------------------
  |  |  |  Branch (1361:32): [Folded, False: 5.57k]
  |  |  ------------------
  ------------------
10863|       |
10864|  5.57k|  if (ifp->dhcp_name[0] == '\0')  // If DHCP name is not set, use "mip"
  ------------------
  |  Branch (10864:7): [True: 5.57k, False: 0]
  ------------------
10865|  5.57k|    memcpy(ifp->dhcp_name, "mip", 4);
10866|  5.57k|  ifp->dhcp_name[sizeof(ifp->dhcp_name) - 1] = '\0';  // Just in case
10867|       |
10868|  5.57k|  if (ifp->driver->init && !ifp->driver->init(ifp)) {
  ------------------
  |  Branch (10868:7): [True: 5.57k, False: 0]
  |  Branch (10868:28): [True: 0, False: 5.57k]
  ------------------
10869|      0|    MG_ERROR(("driver init failed"));
  ------------------
  |  | 1823|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10870|  5.57k|  } else {
10871|  5.57k|    ifp->tx.buf = (char *) mg_calloc(1, ifp->framesize),
10872|  5.57k|    ifp->tx.len = ifp->framesize;
10873|  5.57k|    if (ifp->recv_queue.size == 0)
  ------------------
  |  Branch (10873:9): [True: 5.57k, False: 0]
  ------------------
10874|  5.57k|      ifp->recv_queue.size = ifp->driver->rx ? ifp->framesize : 8192;
  ------------------
  |  Branch (10874:30): [True: 5.57k, False: 0]
  ------------------
10875|  5.57k|    ifp->recv_queue.buf = (char *) mg_calloc(1, ifp->recv_queue.size);
10876|  5.57k|    ifp->timer_1000ms = mg_millis();
10877|  5.57k|    mgr->ifp = ifp;
10878|  5.57k|    ifp->mgr = mgr;
10879|  5.57k|    mgr->extraconnsize = sizeof(struct connstate);
10880|  5.57k|    if (ifp->ip == 0 && ifp->l2type != MG_TCPIP_L2_PPP &&
  ------------------
  |  Branch (10880:9): [True: 0, False: 5.57k]
  |  Branch (10880:25): [True: 0, False: 0]
  ------------------
10881|      0|        ifp->l2type != MG_TCPIP_L2_PPPoE)
  ------------------
  |  Branch (10881:9): [True: 0, False: 0]
  ------------------
10882|      0|      ifp->enable_dhcp_client = true;
10883|  5.57k|    mg_random(&ifp->eport, sizeof(ifp->eport));  // Random from 0 to 65535
10884|  5.57k|    ifp->eport |= MG_EPHEMERAL_PORT_BASE;        // Random from
  ------------------
  |  | 8612|  5.57k|#define MG_EPHEMERAL_PORT_BASE 32768
  ------------------
10885|       |                                           // MG_EPHEMERAL_PORT_BASE to 65535
10886|  5.57k|    if (ifp->tx.buf == NULL || ifp->recv_queue.buf == NULL) MG_ERROR(("OOM"));
  ------------------
  |  | 1823|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (10886:9): [True: 0, False: 5.57k]
  |  Branch (10886:32): [True: 0, False: 5.57k]
  ------------------
10887|  5.57k|    MG_DEBUG(("Builtin TCP/IP init done. Queue size: %zu, extra conn size: %zu",
  ------------------
  |  | 1825|  5.57k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|  5.57k|  do {                      \
  |  |  |  | 1814|  5.57k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  5.57k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10888|  5.57k|              ifp->recv_queue.size, mgr->extraconnsize));
10889|  5.57k|  }
10890|  5.57k|  mg_bsd_init(mgr);
10891|  5.57k|}
mg_tcpip_free:
10899|  5.57k|void mg_tcpip_free(struct mg_tcpip_if *ifp) {
10900|  5.57k|  while (ifp->mgr->conns != NULL) close_conn(ifp->mgr->conns); // TCP FIN wait
  ------------------
  |  Branch (10900:10): [True: 0, False: 5.57k]
  ------------------
10901|  5.57k|  mg_free(ifp->recv_queue.buf);
10902|  5.57k|  mg_free(ifp->tx.buf);
10903|  5.57k|  mg_free(ifp->dns4_url);
10904|  5.57k|}
mg_connect_resolved:
10923|  5.57k|void mg_connect_resolved(struct mg_connection *c) {
10924|  5.57k|  struct mg_tcpip_if *ifp = c->mgr->ifp;
10925|  5.57k|  uint8_t *l2addr;
10926|  5.57k|  struct connstate *s = (struct connstate *) (c + 1);
10927|  5.57k|  s->retransmit = ifp->enable_tcp_retransmit;
10928|  5.57k|  s->txq.align = MG_TCPIP_TXQ_ALIGN;
  ------------------
  |  | 8637|  5.57k|#define MG_TCPIP_TXQ_ALIGN 1024  // Retransmit queue allocation quantum
  ------------------
10929|  5.57k|  c->is_resolving = 0;
10930|  5.57k|  if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE;
  ------------------
  |  | 8612|  5.57k|#define MG_EPHEMERAL_PORT_BASE 32768
  ------------------
                if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE;
  ------------------
  |  | 8612|      0|#define MG_EPHEMERAL_PORT_BASE 32768
  ------------------
  |  Branch (10930:7): [True: 0, False: 5.57k]
  ------------------
10931|  5.57k|  c->loc.port = mg_htons(ifp->eport++);
  ------------------
  |  | 2094|  5.57k|#define mg_htons(x) mg_ntohs(x)
  ------------------
10932|       |#if MG_ENABLE_IPV6
10933|       |  if (c->rem.is_ip6) {
10934|       |    if (c->rem.addr.ip6[0] == ifp->ip6ll[0]) {  // same local LAN, use ll
10935|       |      c->loc.addr.ip6[0] = ifp->ip6ll[0], c->loc.addr.ip6[1] = ifp->ip6ll[1];
10936|       |    } else {  // use global address
10937|       |      c->loc.addr.ip6[0] = ifp->ip6[0], c->loc.addr.ip6[1] = ifp->ip6[1];
10938|       |    }
10939|       |    c->loc.is_ip6 = true;
10940|       |  } else
10941|       |#endif
10942|  5.57k|  {
10943|  5.57k|    c->loc.addr.ip4 = ifp->ip;
10944|  5.57k|  }
10945|  5.57k|  MG_DEBUG(("%lu %M -> %M", c->id, mg_print_ip_port, &c->loc, mg_print_ip_port,
  ------------------
  |  | 1825|  5.57k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|  5.57k|  do {                      \
  |  |  |  | 1814|  5.57k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  5.57k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10946|  5.57k|            &c->rem));
10947|  5.57k|  mg_call(c, MG_EV_RESOLVE, NULL);
10948|  5.57k|  c->is_connecting = 1;
10949|  5.57k|  if (c->is_udp && (l2addr = tcpip_mapip(ifp, &c->rem)) != NULL) {
  ------------------
  |  Branch (10949:7): [True: 0, False: 5.57k]
  |  Branch (10949:20): [True: 0, False: 0]
  ------------------
10950|      0|    memcpy(s->mac, l2addr, sizeof(s->mac));
10951|      0|    l2addr_resolved(c);  // broadcast or multicast
10952|       |#if MG_ENABLE_IPV6
10953|       |  } else if (c->rem.is_ip6) {
10954|       |    if (match_prefix((uint8_t *) c->rem.addr.ip6, ifp->prefix,
10955|       |                     ifp->prefix_len)                       // same global LAN
10956|       |        || (c->rem.addr.ip6[0] == ifp->ip6ll[0]             // same local LAN
10957|       |            && !MG_IP6MATCH(c->rem.addr.ip6, ifp->gw6))) {  // and not gw
10958|       |      // If we're in the same LAN, fire a Neighbor Solicitation
10959|       |      MG_DEBUG(("%lu NS lookup...", c->id));
10960|       |      tx_ndp_ns(ifp, c->rem.addr.ip6, NULL);  // RFC-4861 4.3, requesting
10961|       |      settmout(c, MIP_TTYPE_ARP);
10962|       |      c->is_arplooking = 1;
10963|       |    } else if (ifp->gw6_ready) {
10964|       |      memcpy(s->mac, ifp->gw6mac, sizeof(s->mac));
10965|       |      l2addr_resolved(c);
10966|       |    } else {
10967|       |      mg_error(c, "No IPv6 gateway, can't connect");
10968|       |    }
10969|       |#endif
10970|  5.57k|  } else {
10971|  5.57k|    uint32_t rem_ip = c->rem.addr.ip4;
10972|  5.57k|    if (ifp->ip && ((rem_ip & ifp->mask) == (ifp->ip & ifp->mask)) &&
  ------------------
  |  Branch (10972:9): [True: 5.57k, False: 0]
  |  Branch (10972:20): [True: 0, False: 5.57k]
  ------------------
10973|      0|        rem_ip != ifp->gw) {  // skip if gw (onstatechange -> ARP)
  ------------------
  |  Branch (10973:9): [True: 0, False: 0]
  ------------------
10974|       |      // If we're in the same LAN, fire an ARP lookup.
10975|      0|      MG_DEBUG(("%lu ARP lookup...", c->id));
  ------------------
  |  | 1825|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10976|      0|      mg_tcpip_arp_request(ifp, rem_ip, NULL);
10977|      0|      settmout(c, MIP_TTYPE_ARP);
  ------------------
  |  | 8655|      0|#define MIP_TTYPE_ARP 2        // ARP resolve sent, waiting for response
  ------------------
10978|      0|      c->is_arplooking = 1;
10979|  5.57k|    } else if (ifp->gw_ready) {
  ------------------
  |  Branch (10979:16): [True: 5.57k, False: 0]
  ------------------
10980|  5.57k|      memcpy(s->mac, ifp->gwmac, sizeof(s->mac));
10981|  5.57k|      l2addr_resolved(c);
10982|  5.57k|    } else {
10983|      0|      mg_error(c, "No gateway, can't connect");
10984|      0|    }
10985|  5.57k|  }
10986|  5.57k|}
mg_mgr_poll:
11014|  5.57k|void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
11015|  5.57k|  struct mg_connection *c, *tmp;
11016|  5.57k|  uint64_t now = mg_millis();
11017|  5.57k|  mg_timer_poll(&mgr->timers, now);
11018|  5.57k|  mg_ota_poll(mgr);
11019|  5.57k|  mg_mdash_poll(mgr);
11020|  5.57k|  if (mgr->ifp == NULL || mgr->ifp->driver == NULL) return;
  ------------------
  |  Branch (11020:7): [True: 0, False: 5.57k]
  |  Branch (11020:27): [True: 0, False: 5.57k]
  ------------------
11021|  5.57k|  mg_tcpip_poll(mgr->ifp, now);
11022|  11.1k|  for (c = mgr->conns; c != NULL; c = tmp) {
  ------------------
  |  Branch (11022:24): [True: 5.57k, False: 5.57k]
  ------------------
11023|  5.57k|    struct connstate *s = (struct connstate *) (c + 1);
11024|  5.57k|    long flush = 0;
11025|  5.57k|    bool is_tls = c->is_tls && !c->is_resolving && !c->is_arplooking &&
  ------------------
  |  Branch (11025:19): [True: 0, False: 5.57k]
  |  Branch (11025:32): [True: 0, False: 0]
  |  Branch (11025:52): [True: 0, False: 0]
  ------------------
11026|      0|                  !c->is_listening && !c->is_connecting;
  ------------------
  |  Branch (11026:19): [True: 0, False: 0]
  |  Branch (11026:39): [True: 0, False: 0]
  ------------------
11027|  5.57k|    tmp = c->next;
11028|  5.57k|    mg_call(c, MG_EV_POLL, &now);
11029|  5.57k|    MG_VERBOSE(("%lu .. %c%c%c%c%c%c %lu %lu", c->id, c->is_tls ? 'T' : 't',
  ------------------
  |  | 1826|  5.57k|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1813|  5.57k|  do {                      \
  |  |  |  | 1814|  5.57k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 5.57k]
  |  |  |  |  |  Branch (1814:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1814:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1814:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1814:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1814:19): [True: 0, False: 0]
  |  |  |  |  |  Branch (1814:19): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|  5.57k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
11030|  5.57k|                c->is_connecting ? 'C' : 'c', c->is_tls_hs ? 'H' : 'h',
11031|  5.57k|                c->is_resolving ? 'R' : 'r', c->is_closing ? 'C' : 'c',
11032|  5.57k|                s->is_closing ? 'F' : 'f', mg_tls_pending(c), c->rtls.len));
11033|  5.57k|    if (!c->is_closing) {
  ------------------
  |  Branch (11033:9): [True: 0, False: 5.57k]
  ------------------
11034|       |      // order is important, TLS conn close with > 1 record in buffer (below)
11035|      0|      if (is_tls && (c->rtls.len > 0 || mg_tls_pending(c) > 0))
  ------------------
  |  Branch (11035:11): [True: 0, False: 0]
  |  Branch (11035:22): [True: 0, False: 0]
  |  Branch (11035:41): [True: 0, False: 0]
  ------------------
11036|      0|      c->is_tls_hs ? mg_tls_handshake(c) : handle_tls_recv(c);
  ------------------
  |  Branch (11036:7): [True: 0, False: 0]
  ------------------
11037|      0|      if (can_write(c)) write_conn(c);
  ------------------
  |  Branch (11037:11): [True: 0, False: 0]
  ------------------
11038|      0|      if (is_tls && c->send.len == 0) flush = mg_tls_flush(c);
  ------------------
  |  Branch (11038:11): [True: 0, False: 0]
  |  Branch (11038:21): [True: 0, False: 0]
  ------------------
11039|      0|    }
11040|  5.57k|    if (flush == MG_IO_ERR) proto_error(c, false, "tx err"); // should RST but
  ------------------
  |  Branch (11040:9): [True: 0, False: 5.57k]
  ------------------
11041|  5.57k|    if (c->is_draining && c->send.len == 0 &&
  ------------------
  |  Branch (11041:9): [True: 2.46k, False: 3.11k]
  |  Branch (11041:27): [True: 2.21k, False: 250]
  ------------------
11042|  2.21k|        (c->is_udp ||
  ------------------
  |  Branch (11042:10): [True: 0, False: 2.21k]
  ------------------
11043|  2.21k|         (flush == 0 && s->txq.len == 0 && s->ttype != MIP_TTYPE_FIN)))
  ------------------
  |  | 8657|  2.21k|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
  |  Branch (11043:11): [True: 2.21k, False: 0]
  |  Branch (11043:25): [True: 2.21k, False: 0]
  |  Branch (11043:44): [True: 2.21k, False: 0]
  ------------------
11044|  2.21k|      c->is_closing = 1;
11045|       |    // For non-TLS, close immediately upon completing the 3-way closure
11046|       |    // For TLS, handle any pending data (above) until MIP_TTYPE_FIN expires
11047|  5.57k|    if (s->twclosure &&
  ------------------
  |  Branch (11047:9): [True: 0, False: 5.57k]
  ------------------
11048|      0|        (!c->is_tls || (c->rtls.len == 0 && mg_tls_pending(c) == 0))) {
  ------------------
  |  Branch (11048:10): [True: 0, False: 0]
  |  Branch (11048:25): [True: 0, False: 0]
  |  Branch (11048:45): [True: 0, False: 0]
  ------------------
11049|      0|      s->is_closing = 1;
11050|  5.57k|    } else if (c->is_closing && !s->is_closing) {
  ------------------
  |  Branch (11050:16): [True: 5.57k, False: 0]
  |  Branch (11050:33): [True: 585, False: 4.99k]
  ------------------
11051|    585|      if (c->is_udp || c->is_listening || c->is_resolving || c->is_arplooking ||
  ------------------
  |  Branch (11051:11): [True: 0, False: 585]
  |  Branch (11051:24): [True: 0, False: 585]
  |  Branch (11051:43): [True: 0, False: 585]
  |  Branch (11051:62): [True: 0, False: 585]
  ------------------
11052|    585|          c->is_connecting) {
  ------------------
  |  Branch (11052:11): [True: 585, False: 0]
  ------------------
11053|    585|        close_conn(c);
11054|    585|        continue;
11055|    585|      } else if (s->ttype != MIP_TTYPE_FIN) {  // active TCP: initiate closure
  ------------------
  |  | 8657|      0|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
  |  Branch (11055:18): [True: 0, False: 0]
  ------------------
11056|      0|        size_t tx = tx_tcp(c->mgr->ifp, s->mac, &c->loc, &c->rem, c->dscp,
11057|      0|                           TH_FIN | TH_ACK, mg_htonl(s->seq), mg_htonl(s->ack),
  ------------------
  |  | 8744|      0|#define TH_FIN 0x01
  ------------------
                                         TH_FIN | TH_ACK, mg_htonl(s->seq), mg_htonl(s->ack),
  ------------------
  |  | 8748|      0|#define TH_ACK 0x10
  ------------------
                                         TH_FIN | TH_ACK, mg_htonl(s->seq), mg_htonl(s->ack),
  ------------------
  |  | 2095|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
                                         TH_FIN | TH_ACK, mg_htonl(s->seq), mg_htonl(s->ack),
  ------------------
  |  | 2095|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
11058|      0|                           s->is_full ? 0 : MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 8629|      0|#define MG_TCPIP_WIN 6000  // TCP window size
  ------------------
  |  Branch (11058:28): [True: 0, False: 0]
  ------------------
11059|      0|        if (tx == (size_t) -1) {
  ------------------
  |  Branch (11059:13): [True: 0, False: 0]
  ------------------
11060|      0|          s->is_closing = 1;
11061|      0|        } else if (tx > 0) {
  ------------------
  |  Branch (11061:20): [True: 0, False: 0]
  ------------------
11062|      0|          s->seq++;
11063|      0|          settmout(c, MIP_TTYPE_FIN);
  ------------------
  |  | 8657|      0|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
11064|      0|        }  // else tx = 0, should recover later or we have worse problems
11065|      0|      }
11066|    585|    }
11067|  4.99k|    if (s->send_rst)  // proto_error requested TCP RST, send it and close
  ------------------
  |  Branch (11067:9): [True: 0, False: 4.99k]
  ------------------
11068|      0|      tx_tcp(c->mgr->ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_RST,
  ------------------
  |  | 8746|      0|#define TH_RST 0x04
  ------------------
11069|      0|             mg_htonl(s->seq), 0, 0, NULL, 0);
  ------------------
  |  | 2095|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
11070|  4.99k|    if (s->is_closing) close_conn(c);  // then removes the conn
  ------------------
  |  Branch (11070:9): [True: 4.99k, False: 0]
  ------------------
11071|  4.99k|  }
11072|  5.57k|  mg_bsd_poll(mgr);
11073|  5.57k|  (void) ms;
11074|  5.57k|}
mg_ota_poll:
11378|  5.57k|void mg_ota_poll(struct mg_mgr *mgr) {
11379|  5.57k|  static uint64_t t = 5000;  // Fire first time 5 sec after boot
11380|       |
11381|  5.57k|  static uint64_t feed_timer;  // Advances 500ms per tick; tracks elapsed time
11382|  5.57k|  if (MG_OTA_STATE_GET() == MG_OTA_FAILED &&
  ------------------
  |  | 4314|  5.57k|#define MG_OTA_STATE_GET() 0
  ------------------
  |  Branch (11382:7): [Folded, False: 5.57k]
  ------------------
11383|      0|      mg_timer_expired(&feed_timer, 500, mg_millis())) {
  ------------------
  |  Branch (11383:7): [True: 0, False: 0]
  ------------------
11384|      0|    if (feed_timer < (uint64_t) MG_OTA_ROLLBACK_TIMEOUT_SECONDS * 1000) {
  ------------------
  |  | 4325|      0|#define MG_OTA_ROLLBACK_TIMEOUT_SECONDS 120
  ------------------
  |  Branch (11384:9): [True: 0, False: 0]
  ------------------
11385|      0|      MG_OTA_ROLLBACK_TIMER_FEED();  // Feed watchdog every 500ms
11386|      0|    } else if (s_autocommit_ok) {
  ------------------
  |  Branch (11386:16): [True: 0, False: 0]
  ------------------
11387|      0|      MG_INFO(("Auto-committing firmware"));
  ------------------
  |  | 1824|      0|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
11388|      0|      MG_OTA_STATE_SET(MG_OTA_CONFIRMED);  // Stop feeding → IWDG resets cleanly
  ------------------
  |  | 4317|      0|#define MG_OTA_STATE_SET(val) (void) (val)
  ------------------
11389|      0|    } else {
11390|      0|      MG_INFO(("No commit confirmation, rolling back"));
  ------------------
  |  | 1824|      0|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
11391|       |      // Stop feeding → IWDG fires → resets into MG_OTA_FAILED → rollback
11392|      0|    }
11393|      0|  }
11394|       |
11395|  5.57k|  if (MG_OTA_URL != NULL &&
  ------------------
  |  | 4368|  5.57k|#define MG_OTA_URL NULL
  ------------------
  |  Branch (11395:7): [Folded, False: 5.57k]
  ------------------
11396|      0|      mg_timer_expired(&t, MG_OTA_PULL_INTERVAL_SECONDS * 1000, mg_millis())) {
  ------------------
  |  | 4394|      0|#define MG_OTA_PULL_INTERVAL_SECONDS 60
  ------------------
  |  Branch (11396:7): [True: 0, False: 0]
  ------------------
11397|      0|    mg_ota_url_check(mgr, MG_OTA_URL, MG_OTA_STATUS_FN);
  ------------------
  |  | 4368|      0|#define MG_OTA_URL NULL
  ------------------
                  mg_ota_url_check(mgr, MG_OTA_URL, MG_OTA_STATUS_FN);
  ------------------
  |  | 4379|      0|#define MG_OTA_STATUS_FN NULL
  ------------------
11398|      0|  }
11399|  5.57k|}
mg_pfn_iobuf_noresize:
13698|  9.18M|void mg_pfn_iobuf_noresize(char ch, void *param) {
13699|  9.18M|  mg_pfn_iobuf_private(ch, param, false);
13700|  9.18M|}
mg_pfn_iobuf:
13702|  13.9M|void mg_pfn_iobuf(char ch, void *param) {
13703|  13.9M|  mg_pfn_iobuf_private(ch, param, true);
13704|  13.9M|}
mg_vsnprintf:
13706|   978k|size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap) {
13707|   978k|  struct mg_iobuf io = {0, 0, 0, 0};
13708|   978k|  size_t n;
13709|   978k|  io.buf = (uint8_t *) buf, io.size = len;
13710|   978k|  n = mg_vxprintf(mg_pfn_iobuf_noresize, &io, fmt, ap);
13711|   978k|  if (n < len) buf[n] = '\0';
  ------------------
  |  Branch (13711:7): [True: 977k, False: 1.03k]
  ------------------
13712|   978k|  return n;
13713|   978k|}
mg_snprintf:
13715|   972k|size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...) {
13716|   972k|  va_list ap;
13717|   972k|  size_t n;
13718|   972k|  va_start(ap, fmt);
13719|   972k|  n = mg_vsnprintf(buf, len, fmt, &ap);
13720|       |  va_end(ap);
13721|   972k|  return n;
13722|   972k|}
mg_pfn_stdout:
13739|   184k|void mg_pfn_stdout(char c, void *param) {
13740|   184k|#if MG_ENABLE_POSIX_FS
13741|   184k|  putchar(c);
13742|   184k|#endif
13743|   184k|  (void) param, (void) c;
13744|   184k|}
mg_sntp_parse:
14721|  11.1k|int64_t mg_sntp_parse(const unsigned char *buf, size_t len) {
14722|  11.1k|  int64_t epoch_milliseconds = -1;
14723|  11.1k|  int mode = len > 0 ? buf[0] & 7 : 0;
  ------------------
  |  Branch (14723:14): [True: 5.57k, False: 5.57k]
  ------------------
14724|  11.1k|  int version = len > 0 ? (buf[0] >> 3) & 7 : 0;
  ------------------
  |  Branch (14724:17): [True: 5.57k, False: 5.57k]
  ------------------
14725|  11.1k|  if (len < 48) {
  ------------------
  |  Branch (14725:7): [True: 8.65k, False: 2.49k]
  ------------------
14726|  8.65k|    MG_ERROR(("%s", "corrupt packet"));
  ------------------
  |  | 1823|  8.65k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|  8.65k|  do {                      \
  |  |  |  | 1814|  8.65k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 8.65k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  8.65k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 8.65k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
14727|  8.65k|  } else if (mode != 4 && mode != 5) {
  ------------------
  |  Branch (14727:14): [True: 2.40k, False: 91]
  |  Branch (14727:27): [True: 2.24k, False: 163]
  ------------------
14728|  2.24k|    MG_ERROR(("%s", "not a server reply"));
  ------------------
  |  | 1823|  2.24k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|  2.24k|  do {                      \
  |  |  |  | 1814|  2.24k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 2.24k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  2.24k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 2.24k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
14729|  2.24k|  } else if (buf[1] == 0) {
  ------------------
  |  Branch (14729:14): [True: 3, False: 251]
  ------------------
14730|      3|    MG_ERROR(("%s", "server sent a kiss of death"));
  ------------------
  |  | 1823|      3|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|      3|  do {                      \
  |  |  |  | 1814|      3|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 3]
  |  |  |  |  ------------------
  |  |  |  | 1815|      3|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 3]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
14731|    251|  } else if (version == 4 || version == 3) {
  ------------------
  |  Branch (14731:14): [True: 64, False: 187]
  |  Branch (14731:30): [True: 120, False: 67]
  ------------------
14732|       |    // int64_t ref = gettimestamp((uint32_t *) &buf[16]);
14733|    184|    int64_t origin_time = gettimestamp((uint32_t *) &buf[24]);
14734|    184|    int64_t receive_time = gettimestamp((uint32_t *) &buf[32]);
14735|    184|    int64_t transmit_time = gettimestamp((uint32_t *) &buf[40]);
14736|    184|    int64_t now = (int64_t) mg_millis();
14737|    184|    int64_t latency = (now - origin_time) - (transmit_time - receive_time);
14738|    184|    epoch_milliseconds = transmit_time + latency / 2;
14739|    184|    mg_boot_timestamp_ms = (uint64_t) (epoch_milliseconds - now);
14740|    184|  } else {
14741|     67|    MG_ERROR(("unexpected version: %d", version));
  ------------------
  |  | 1823|     67|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|     67|  do {                      \
  |  |  |  | 1814|     67|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 67]
  |  |  |  |  ------------------
  |  |  |  | 1815|     67|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 67]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
14742|     67|  }
14743|  11.1k|  return epoch_milliseconds;
14744|  11.1k|}
mg_str_s:
15721|  1.38M|struct mg_str mg_str_s(const char *s) {
15722|  1.38M|  struct mg_str str;
15723|  1.38M|  str.buf = (char *) s, str.len = (s == NULL) ? 0 : strlen(s);
  ------------------
  |  Branch (15723:35): [True: 21.5k, False: 1.36M]
  ------------------
15724|  1.38M|  return str;
15725|  1.38M|}
mg_str_n:
15727|  3.99M|struct mg_str mg_str_n(const char *s, size_t n) {
15728|  3.99M|  struct mg_str str;
15729|  3.99M|  str.buf = (char *) s, str.len = n;
15730|  3.99M|  return str;
15731|  3.99M|}
mg_strcmp:
15760|  1.08M|int mg_strcmp(const struct mg_str str1, const struct mg_str str2) {
15761|  1.08M|  size_t i = 0;
15762|  1.46M|  while (i < str1.len && i < str2.len) {
  ------------------
  |  Branch (15762:10): [True: 1.07M, False: 389k]
  |  Branch (15762:26): [True: 1.07M, False: 7.82k]
  ------------------
15763|  1.07M|    int c1 = str1.buf[i];
15764|  1.07M|    int c2 = str2.buf[i];
15765|  1.07M|    if (c1 < c2) return -1;
  ------------------
  |  Branch (15765:9): [True: 662k, False: 408k]
  ------------------
15766|   408k|    if (c1 > c2) return 1;
  ------------------
  |  Branch (15766:9): [True: 26.0k, False: 382k]
  ------------------
15767|   382k|    i++;
15768|   382k|  }
15769|   397k|  if (i < str1.len) return 1;
  ------------------
  |  Branch (15769:7): [True: 7.82k, False: 389k]
  ------------------
15770|   389k|  if (i < str2.len) return -1;
  ------------------
  |  Branch (15770:7): [True: 16.7k, False: 372k]
  ------------------
15771|   372k|  return 0;
15772|   389k|}
mg_strcasecmp:
15774|   675k|int mg_strcasecmp(const struct mg_str str1, const struct mg_str str2) {
15775|   675k|  size_t i = 0;
15776|  1.14M|  while (i < str1.len && i < str2.len) {
  ------------------
  |  Branch (15776:10): [True: 1.08M, False: 60.0k]
  |  Branch (15776:26): [True: 1.08M, False: 1.45k]
  ------------------
15777|  1.08M|    int c1 = mg_tolc(str1.buf[i]);
15778|  1.08M|    int c2 = mg_tolc(str2.buf[i]);
15779|  1.08M|    if (c1 < c2) return -1;
  ------------------
  |  Branch (15779:9): [True: 164k, False: 922k]
  ------------------
15780|   922k|    if (c1 > c2) return 1;
  ------------------
  |  Branch (15780:9): [True: 449k, False: 472k]
  ------------------
15781|   472k|    i++;
15782|   472k|  }
15783|  61.5k|  if (i < str1.len) return 1;
  ------------------
  |  Branch (15783:7): [True: 1.45k, False: 60.0k]
  ------------------
15784|  60.0k|  if (i < str2.len) return -1;
  ------------------
  |  Branch (15784:7): [True: 19.7k, False: 40.3k]
  ------------------
15785|  40.3k|  return 0;
15786|  60.0k|}
mg_match:
15788|  7.36k|bool mg_match(struct mg_str s, struct mg_str p, struct mg_str *caps) {
15789|  7.36k|  size_t i = 0, j = 0, ni = 0, nj = 0;
15790|  7.36k|  if (caps) caps->buf = NULL, caps->len = 0;
  ------------------
  |  Branch (15790:7): [True: 0, False: 7.36k]
  ------------------
15791|   194M|  while (i < p.len || j < s.len) {
  ------------------
  |  Branch (15791:10): [True: 194M, False: 11.1k]
  |  Branch (15791:23): [True: 5.26k, False: 5.84k]
  ------------------
15792|   194M|    if (i < p.len && j < s.len &&
  ------------------
  |  Branch (15792:9): [True: 194M, False: 5.26k]
  |  Branch (15792:22): [True: 194M, False: 2.30k]
  ------------------
15793|   194M|        (p.buf[i] == '?' ||
  ------------------
  |  Branch (15793:10): [True: 98.9k, False: 194M]
  ------------------
15794|   194M|         (p.buf[i] != '*' && p.buf[i] != '#' && s.buf[j] == p.buf[i]))) {
  ------------------
  |  Branch (15794:11): [True: 191M, False: 2.84M]
  |  Branch (15794:30): [True: 191M, False: 133k]
  |  Branch (15794:49): [True: 189M, False: 1.57M]
  ------------------
15795|   189M|      if (caps == NULL) {
  ------------------
  |  Branch (15795:11): [True: 189M, False: 0]
  ------------------
15796|   189M|      } else if (p.buf[i] == '?') {
  ------------------
  |  Branch (15796:18): [True: 0, False: 0]
  ------------------
15797|      0|        caps->buf = &s.buf[j], caps->len = 1;     // Finalize `?` cap
15798|      0|        caps++, caps->buf = NULL, caps->len = 0;  // Init next cap
15799|      0|      } else if (caps->buf != NULL && caps->len == 0) {
  ------------------
  |  Branch (15799:18): [True: 0, False: 0]
  |  Branch (15799:39): [True: 0, False: 0]
  ------------------
15800|      0|        caps->len = (size_t) (&s.buf[j] - caps->buf);  // Finalize current cap
15801|      0|        caps++, caps->len = 0, caps->buf = NULL;       // Init next cap
15802|      0|      }
15803|   189M|      i++, j++;
15804|   189M|    } else if (i < p.len && (p.buf[i] == '*' || p.buf[i] == '#')) {
  ------------------
  |  Branch (15804:16): [True: 4.55M, False: 5.26k]
  |  Branch (15804:30): [True: 2.84M, False: 1.70M]
  |  Branch (15804:49): [True: 133k, False: 1.57M]
  ------------------
15805|  2.97M|      if (caps && !caps->buf) caps->len = 0, caps->buf = &s.buf[j];  // Init cap
  ------------------
  |  Branch (15805:11): [True: 0, False: 2.97M]
  |  Branch (15805:19): [True: 0, False: 0]
  ------------------
15806|  2.97M|      ni = i++, nj = j + 1;
15807|  2.97M|    } else if (nj > 0 && nj <= s.len &&
  ------------------
  |  Branch (15807:16): [True: 1.57M, False: 0]
  |  Branch (15807:26): [True: 1.57M, False: 811]
  ------------------
15808|  1.57M|               ((ni < p.len && p.buf[ni] == '#') ||
  ------------------
  |  Branch (15808:18): [True: 1.57M, False: 0]
  |  Branch (15808:32): [True: 69.9k, False: 1.50M]
  ------------------
15809|  1.57M|                (j < s.len && s.buf[j] != '/'))) {
  ------------------
  |  Branch (15809:18): [True: 1.50M, False: 296]
  |  Branch (15809:31): [True: 1.50M, False: 412]
  ------------------
15810|  1.57M|      i = ni, j = nj;
15811|  1.57M|      if (caps && caps->buf == NULL && caps->len == 0) {
  ------------------
  |  Branch (15811:11): [True: 0, False: 1.57M]
  |  Branch (15811:19): [True: 0, False: 0]
  |  Branch (15811:40): [True: 0, False: 0]
  ------------------
15812|      0|        caps--, caps->len = 0;  // Restart previous cap
15813|      0|      }
15814|  1.57M|    } else {
15815|  1.51k|      return false;
15816|  1.51k|    }
15817|   194M|  }
15818|  5.84k|  if (caps && caps->buf && caps->len == 0) {
  ------------------
  |  Branch (15818:7): [True: 0, False: 5.84k]
  |  Branch (15818:15): [True: 0, False: 0]
  |  Branch (15818:28): [True: 0, False: 0]
  ------------------
15819|      0|    caps->len = (size_t) (&s.buf[j] - caps->buf);
15820|      0|  }
15821|  5.84k|  return true;
15822|  7.36k|}
mg_span:
15824|  1.96M|bool mg_span(struct mg_str s, struct mg_str *a, struct mg_str *b, char sep) {
15825|  1.96M|  if (s.len == 0 || s.buf == NULL) {
  ------------------
  |  Branch (15825:7): [True: 250k, False: 1.71M]
  |  Branch (15825:21): [True: 0, False: 1.71M]
  ------------------
15826|   250k|    return false;  // Empty string, nothing to span - fail
15827|  1.71M|  } else {
15828|  1.71M|    size_t len = 0;
15829|   539M|    while (len < s.len && s.buf[len] != sep) len++;  // Find separator
  ------------------
  |  Branch (15829:12): [True: 538M, False: 535k]
  |  Branch (15829:27): [True: 537M, False: 1.18M]
  ------------------
15830|  1.71M|    if (a) *a = mg_str_n(s.buf, len);                // Init a
  ------------------
  |  Branch (15830:9): [True: 1.71M, False: 0]
  ------------------
15831|  1.71M|    if (b) *b = mg_str_n(s.buf + len, s.len - len);  // Init b
  ------------------
  |  Branch (15831:9): [True: 1.71M, False: 0]
  ------------------
15832|  1.71M|    if (b && len < s.len) b->buf++, b->len--;        // Skip separator
  ------------------
  |  Branch (15832:9): [True: 1.71M, False: 0]
  |  Branch (15832:14): [True: 1.18M, False: 535k]
  ------------------
15833|  1.71M|    return true;
15834|  1.71M|  }
15835|  1.96M|}
mg_str_to_num:
15837|  67.4k|bool mg_str_to_num(struct mg_str str, int base, void *val, size_t val_len) {
15838|  67.4k|  size_t i = 0, ndigits = 0;
15839|  67.4k|  uint64_t max = val_len == sizeof(uint8_t)    ? 0xFF
  ------------------
  |  Branch (15839:18): [True: 46.4k, False: 21.0k]
  ------------------
15840|  67.4k|                 : val_len == sizeof(uint16_t) ? 0xFFFF
  ------------------
  |  Branch (15840:20): [True: 0, False: 21.0k]
  ------------------
15841|  21.0k|                 : val_len == sizeof(uint32_t) ? 0xFFFFFFFF
  ------------------
  |  Branch (15841:20): [True: 21.0k, False: 0]
  ------------------
15842|  21.0k|                                               : (uint64_t) ~0;
15843|  67.4k|  uint64_t result = 0;
15844|  67.4k|  if (max == (uint64_t) ~0 && val_len != sizeof(uint64_t)) return false;
  ------------------
  |  Branch (15844:7): [True: 0, False: 67.4k]
  |  Branch (15844:31): [True: 0, False: 0]
  ------------------
15845|  67.4k|  if (base == 0 && str.len >= 2) {
  ------------------
  |  Branch (15845:7): [True: 0, False: 67.4k]
  |  Branch (15845:20): [True: 0, False: 0]
  ------------------
15846|      0|    if (str.buf[i] == '0') {
  ------------------
  |  Branch (15846:9): [True: 0, False: 0]
  ------------------
15847|      0|      i++;
15848|      0|      base = str.buf[i] == 'b' ? 2 : str.buf[i] == 'x' ? 16 : 10;
  ------------------
  |  Branch (15848:14): [True: 0, False: 0]
  |  Branch (15848:38): [True: 0, False: 0]
  ------------------
15849|      0|      if (base != 10) ++i;
  ------------------
  |  Branch (15849:11): [True: 0, False: 0]
  ------------------
15850|      0|    } else {
15851|      0|      base = 10;
15852|      0|    }
15853|      0|  }
15854|  67.4k|  switch (base) {
15855|      0|    case 2:
  ------------------
  |  Branch (15855:5): [True: 0, False: 67.4k]
  ------------------
15856|      0|      while (i < str.len && (str.buf[i] == '0' || str.buf[i] == '1')) {
  ------------------
  |  Branch (15856:14): [True: 0, False: 0]
  |  Branch (15856:30): [True: 0, False: 0]
  |  Branch (15856:51): [True: 0, False: 0]
  ------------------
15857|      0|        uint64_t digit = (uint64_t) (str.buf[i] - '0');
15858|      0|        if (result > max / 2) return false;  // Overflow
  ------------------
  |  Branch (15858:13): [True: 0, False: 0]
  ------------------
15859|      0|        result *= 2;
15860|      0|        if (result > max - digit) return false;  // Overflow
  ------------------
  |  Branch (15860:13): [True: 0, False: 0]
  ------------------
15861|      0|        result += digit;
15862|      0|        i++, ndigits++;
15863|      0|      }
15864|      0|      break;
15865|      0|    case 10:
  ------------------
  |  Branch (15865:5): [True: 0, False: 67.4k]
  ------------------
15866|      0|      while (i < str.len && str.buf[i] >= '0' && str.buf[i] <= '9') {
  ------------------
  |  Branch (15866:14): [True: 0, False: 0]
  |  Branch (15866:29): [True: 0, False: 0]
  |  Branch (15866:50): [True: 0, False: 0]
  ------------------
15867|      0|        uint64_t digit = (uint64_t) (str.buf[i] - '0');
15868|      0|        if (result > max / 10) return false;  // Overflow
  ------------------
  |  Branch (15868:13): [True: 0, False: 0]
  ------------------
15869|      0|        result *= 10;
15870|      0|        if (result > max - digit) return false;  // Overflow
  ------------------
  |  Branch (15870:13): [True: 0, False: 0]
  ------------------
15871|      0|        result += digit;
15872|      0|        i++, ndigits++;
15873|      0|      }
15874|      0|      break;
15875|  67.4k|    case 16:
  ------------------
  |  Branch (15875:5): [True: 67.4k, False: 0]
  ------------------
15876|  4.98M|      while (i < str.len) {
  ------------------
  |  Branch (15876:14): [True: 4.91M, False: 67.3k]
  ------------------
15877|  4.91M|        char c = str.buf[i];
15878|  4.91M|        uint64_t digit = (c >= '0' && c <= '9')   ? (uint64_t) (c - '0')
  ------------------
  |  Branch (15878:27): [True: 4.91M, False: 0]
  |  Branch (15878:39): [True: 4.82M, False: 89.8k]
  ------------------
15879|  4.91M|                         : (c >= 'A' && c <= 'F') ? (uint64_t) (c - '7')
  ------------------
  |  Branch (15879:29): [True: 89.8k, False: 0]
  |  Branch (15879:41): [True: 6.84k, False: 82.9k]
  ------------------
15880|  89.8k|                         : (c >= 'a' && c <= 'f') ? (uint64_t) (c - 'W')
  ------------------
  |  Branch (15880:29): [True: 82.9k, False: 0]
  |  Branch (15880:41): [True: 82.9k, False: 0]
  ------------------
15881|  82.9k|                                                  : (uint64_t) ~0;
15882|  4.91M|        if (digit == (uint64_t) ~0) break;
  ------------------
  |  Branch (15882:13): [True: 0, False: 4.91M]
  ------------------
15883|  4.91M|        if (result > max / 16) return false;  // Overflow
  ------------------
  |  Branch (15883:13): [True: 34, False: 4.91M]
  ------------------
15884|  4.91M|        result *= 16;
15885|  4.91M|        if (result > max - digit) return false;  // Overflow
  ------------------
  |  Branch (15885:13): [True: 0, False: 4.91M]
  ------------------
15886|  4.91M|        result += digit;
15887|  4.91M|        i++, ndigits++;
15888|  4.91M|      }
15889|  67.3k|      break;
15890|  67.3k|    default: return false;
  ------------------
  |  Branch (15890:5): [True: 0, False: 67.4k]
  ------------------
15891|  67.4k|  }
15892|  67.3k|  if (ndigits == 0) return false;
  ------------------
  |  Branch (15892:7): [True: 0, False: 67.3k]
  ------------------
15893|  67.3k|  if (i != str.len) return false;
  ------------------
  |  Branch (15893:7): [True: 0, False: 67.3k]
  ------------------
15894|  67.3k|  if (val_len == 1) {
  ------------------
  |  Branch (15894:7): [True: 46.4k, False: 20.9k]
  ------------------
15895|  46.4k|    *((uint8_t *) val) = (uint8_t) result;
15896|  46.4k|  } else if (val_len == 2) {
  ------------------
  |  Branch (15896:14): [True: 0, False: 20.9k]
  ------------------
15897|      0|    *((uint16_t *) val) = (uint16_t) result;
15898|  20.9k|  } else if (val_len == 4) {
  ------------------
  |  Branch (15898:14): [True: 20.9k, False: 0]
  ------------------
15899|  20.9k|    *((uint32_t *) val) = (uint32_t) result;
15900|  20.9k|  } else {
15901|      0|    *((uint64_t *) val) = (uint64_t) result;
15902|      0|  }
15903|  67.3k|  return true;
15904|  67.3k|}
mg_timer_expired:
15926|  5.57k|bool mg_timer_expired(uint64_t *t, uint64_t prd, uint64_t now) {
15927|  5.57k|  if (now + prd < *t) *t = 0;                    // Time wrapped? Reset timer
  ------------------
  |  Branch (15927:7): [True: 0, False: 5.57k]
  ------------------
15928|  5.57k|  if (*t == 0) *t = now + prd;                   // Firt poll? Set expiration
  ------------------
  |  Branch (15928:7): [True: 0, False: 5.57k]
  ------------------
15929|  5.57k|  if (*t > now) return false;                    // Not expired yet, return
  ------------------
  |  Branch (15929:7): [True: 0, False: 5.57k]
  ------------------
15930|  5.57k|  *t = (now - *t) > prd ? now + prd : *t + prd;  // Next expiration time
  ------------------
  |  Branch (15930:8): [True: 0, False: 5.57k]
  ------------------
15931|  5.57k|  return true;                                   // Expired, return true
15932|  5.57k|}
mg_timer_poll:
15934|  5.57k|void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) {
15935|  5.57k|  struct mg_timer *t, *tmp;
15936|  5.57k|  for (t = *head; t != NULL; t = tmp) {
  ------------------
  |  Branch (15936:19): [True: 0, False: 5.57k]
  ------------------
15937|      0|    bool once = t->expire == 0 && (t->flags & MG_TIMER_RUN_NOW) &&
  ------------------
  |  | 1837|      0|#define MG_TIMER_RUN_NOW 2     // Call immediately when timer is set
  ------------------
  |  Branch (15937:17): [True: 0, False: 0]
  |  Branch (15937:35): [True: 0, False: 0]
  ------------------
15938|      0|                !(t->flags & MG_TIMER_CALLED);  // Handle MG_TIMER_NOW only once
  ------------------
  |  | 1838|      0|#define MG_TIMER_CALLED 4      // Timer function was called at least once
  ------------------
  |  Branch (15938:17): [True: 0, False: 0]
  ------------------
15939|      0|    bool expired = mg_timer_expired(&t->expire, t->period_ms, now_ms);
15940|      0|    tmp = t->next;
15941|      0|    if (!once && !expired) continue;
  ------------------
  |  Branch (15941:9): [True: 0, False: 0]
  |  Branch (15941:18): [True: 0, False: 0]
  ------------------
15942|      0|    if ((t->flags & MG_TIMER_REPEAT) || !(t->flags & MG_TIMER_CALLED)) {
  ------------------
  |  | 1836|      0|#define MG_TIMER_REPEAT 1      // Call function periodically
  ------------------
                  if ((t->flags & MG_TIMER_REPEAT) || !(t->flags & MG_TIMER_CALLED)) {
  ------------------
  |  | 1838|      0|#define MG_TIMER_CALLED 4      // Timer function was called at least once
  ------------------
  |  Branch (15942:9): [True: 0, False: 0]
  |  Branch (15942:41): [True: 0, False: 0]
  ------------------
15943|      0|      t->fn(t->arg);
15944|      0|    }
15945|      0|    t->flags |= MG_TIMER_CALLED;
  ------------------
  |  | 1838|      0|#define MG_TIMER_CALLED 4      // Timer function was called at least once
  ------------------
15946|       |
15947|       |    // If this timer is not repeating and marked AUTODELETE, remove it
15948|      0|    if (!(t->flags & MG_TIMER_REPEAT) && (t->flags & MG_TIMER_AUTODELETE)) {
  ------------------
  |  | 1836|      0|#define MG_TIMER_REPEAT 1      // Call function periodically
  ------------------
                  if (!(t->flags & MG_TIMER_REPEAT) && (t->flags & MG_TIMER_AUTODELETE)) {
  ------------------
  |  | 1839|      0|#define MG_TIMER_AUTODELETE 8  // mg_free() timer when done
  ------------------
  |  Branch (15948:9): [True: 0, False: 0]
  |  Branch (15948:42): [True: 0, False: 0]
  ------------------
15949|      0|      mg_timer_free(head, t);
15950|      0|      mg_free(t);
15951|      0|    }
15952|      0|  }
15953|  5.57k|}
mg_tls_free:
21442|  5.57k|void mg_tls_free(struct mg_connection *c) {
21443|  5.57k|  (void) c;
21444|  5.57k|}
mg_tls_ctx_init:
21459|  5.57k|void mg_tls_ctx_init(struct mg_mgr *mgr) {
21460|  5.57k|  (void) mgr;
21461|  5.57k|}
mg_tls_ctx_free:
21462|  5.57k|void mg_tls_ctx_free(struct mg_mgr *mgr) {
21463|  5.57k|  (void) mgr;
21464|  5.57k|}
mg_url_is_ssl:
28774|  5.57k|bool mg_url_is_ssl(const char *url) {
28775|  5.57k|  return strncmp(url, "wss:", 4) == 0 || strncmp(url, "https:", 6) == 0 ||
  ------------------
  |  Branch (28775:10): [True: 0, False: 5.57k]
  |  Branch (28775:42): [True: 0, False: 5.57k]
  ------------------
28776|  5.57k|         strncmp(url, "mqtts:", 6) == 0 || strncmp(url, "ssl:", 4) == 0 ||
  ------------------
  |  Branch (28776:10): [True: 0, False: 5.57k]
  |  Branch (28776:44): [True: 0, False: 5.57k]
  ------------------
28777|  5.57k|         strncmp(url, "tls:", 4) == 0 || strncmp(url, "tcps:", 5) == 0;
  ------------------
  |  Branch (28777:10): [True: 0, False: 5.57k]
  |  Branch (28777:42): [True: 0, False: 5.57k]
  ------------------
28778|  5.57k|}
mg_url_host:
28808|  5.57k|struct mg_str mg_url_host(const char *url) {
28809|  5.57k|  struct url u = urlparse(url);
28810|  5.57k|  size_t n = u.port  ? u.port - u.host - 1
  ------------------
  |  Branch (28810:14): [True: 5.57k, False: 0]
  ------------------
28811|  5.57k|             : u.uri ? u.uri - u.host
  ------------------
  |  Branch (28811:16): [True: 0, False: 0]
  ------------------
28812|      0|                     : u.end - u.host;
28813|  5.57k|  struct mg_str s = mg_str_n(url + u.host, n);
28814|  5.57k|  return s;
28815|  5.57k|}
mg_url_port:
28822|  5.57k|unsigned short mg_url_port(const char *url) {
28823|  5.57k|  struct url u = urlparse(url);
28824|  5.57k|  unsigned short port = 0;
28825|  5.57k|  if (strncmp(url, "http:", 5) == 0 || strncmp(url, "ws:", 3) == 0) port = 80;
  ------------------
  |  Branch (28825:7): [True: 5.57k, False: 0]
  |  Branch (28825:40): [True: 0, False: 0]
  ------------------
28826|  5.57k|  if (strncmp(url, "wss:", 4) == 0 || strncmp(url, "https:", 6) == 0)
  ------------------
  |  Branch (28826:7): [True: 0, False: 5.57k]
  |  Branch (28826:39): [True: 0, False: 5.57k]
  ------------------
28827|      0|    port = 443;
28828|  5.57k|  if (strncmp(url, "mqtt:", 5) == 0) port = 1883;
  ------------------
  |  Branch (28828:7): [True: 0, False: 5.57k]
  ------------------
28829|  5.57k|  if (strncmp(url, "mqtts:", 6) == 0) port = 8883;
  ------------------
  |  Branch (28829:7): [True: 0, False: 5.57k]
  ------------------
28830|  5.57k|  if (u.port) port = (unsigned short) atoi(url + u.port);
  ------------------
  |  Branch (28830:7): [True: 5.57k, False: 0]
  ------------------
28831|  5.57k|  return port;
28832|  5.57k|}
mg_bzero:
28863|  36.9k|void mg_bzero(volatile unsigned char *buf, size_t len) {
28864|  36.9k|  if (buf != NULL) {
  ------------------
  |  Branch (28864:7): [True: 14.5k, False: 22.3k]
  ------------------
28865|   248G|    while (len--) *buf++ = 0;
  ------------------
  |  Branch (28865:12): [True: 248G, False: 14.5k]
  ------------------
28866|  14.5k|  }
28867|  36.9k|}
mg_random:
28895|  10.4k|bool mg_random(void *buf, size_t len) {
28896|  10.4k|  bool success = false;
28897|  10.4k|  unsigned char *p = (unsigned char *) buf;
28898|       |#if MG_ARCH == MG_ARCH_ESP32
28899|       |  while (len--) *p++ = (unsigned char) (esp_random() & 255);
28900|       |  success = true;
28901|       |#elif MG_ARCH == MG_ARCH_CUBE && defined(HAL_RNG_MODULE_ENABLED)
28902|       |  extern RNG_HandleTypeDef hrng;
28903|       |  success = true;
28904|       |  for (size_t n = 0; n < len; n += sizeof(uint32_t)) {
28905|       |    uint32_t r = 0;
28906|       |    if (HAL_RNG_GenerateRandomNumber(&hrng, &r) != HAL_OK) success = false;
28907|       |    memcpy((char *) buf + n, &r, n + sizeof(r) > len ? len - n : sizeof(r));
28908|       |  }
28909|       |#elif MG_ARCH == MG_ARCH_PICOSDK
28910|       |  while (len--) *p++ = (unsigned char) (get_rand_32() & 255);
28911|       |  success = true;
28912|       |#elif MG_ARCH == MG_ARCH_ZEPHYR
28913|       |#if MG_TLS == MG_TLS_BUILTIN ||                                    \
28914|       |    (MG_TLS == MG_TLS_MBED && (!defined(MBEDTLS_VERSION_NUMBER) || \
28915|       |                               MBEDTLS_VERSION_NUMBER < 0x04000000))
28916|       |  return (sys_csrand_get(buf, len) == 0);  // do not fallback on reseed error
28917|       |#else
28918|       |  sys_rand_get(buf, len);
28919|       |  success = true;
28920|       |#endif
28921|       |#elif MG_ARCH == MG_ARCH_WIN32
28922|       |#if defined(_MSC_VER) && _MSC_VER < 1700
28923|       |  static bool initialised = false;
28924|       |  static HCRYPTPROV hProv;
28925|       |  // CryptGenRandom() implementation earlier than 2008 is weak, see
28926|       |  // https://en.wikipedia.org/wiki/CryptGenRandom
28927|       |  if (!initialised) {
28928|       |    initialised = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
28929|       |                                      CRYPT_VERIFYCONTEXT);
28930|       |  }
28931|       |  if (initialised) success = CryptGenRandom(hProv, len, p);
28932|       |#else
28933|       |  size_t i;
28934|       |  for (i = 0; i < len; i++) {
28935|       |    unsigned int rand_v;
28936|       |    if (rand_s(&rand_v) == 0) {
28937|       |      p[i] = (unsigned char) (rand_v & 255);
28938|       |    } else {
28939|       |      break;
28940|       |    }
28941|       |  }
28942|       |  success = (i == len);
28943|       |#endif
28944|       |
28945|       |#elif MG_ARCH == MG_ARCH_UNIX
28946|       |  FILE *fp = fopen("/dev/urandom", "rb");
28947|  10.4k|  if (fp != NULL) {
  ------------------
  |  Branch (28947:7): [True: 10.4k, False: 0]
  ------------------
28948|  10.4k|    if (fread(buf, 1, len, fp) == len) success = true;
  ------------------
  |  Branch (28948:9): [True: 10.4k, False: 0]
  ------------------
28949|  10.4k|    fclose(fp);
28950|  10.4k|  }
28951|  10.4k|#endif
28952|       |  // If everything above did not work, fallback to a pseudo random generator
28953|  10.4k|  if (success == false) {
  ------------------
  |  Branch (28953:7): [True: 0, False: 10.4k]
  ------------------
28954|      0|    MG_ERROR(("Weak RNG: using rand()"));
  ------------------
  |  | 1823|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
28955|      0|    while (len--) *p++ = (unsigned char) (rand() & 255);
  ------------------
  |  Branch (28955:12): [True: 0, False: 0]
  ------------------
28956|      0|  }
28957|  10.4k|  return success;
28958|  10.4k|}
mg_crc32:
28974|   152k|uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) {
28975|   152k|  static const uint32_t crclut[16] = {
28976|       |      // table for polynomial 0xEDB88320 (reflected)
28977|   152k|      0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, 0x76DC4190, 0x6B6B51F4,
28978|   152k|      0x4DB26158, 0x5005713C, 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C,
28979|   152k|      0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C};
28980|   152k|  crc = ~crc;
28981|  38.8M|  while (len--) {
  ------------------
  |  Branch (28981:10): [True: 38.7M, False: 152k]
  ------------------
28982|  38.7M|    uint8_t b = *(uint8_t *) buf++;
28983|  38.7M|    crc = crclut[(crc ^ b) & 0x0F] ^ (crc >> 4);
28984|  38.7M|    crc = crclut[(crc ^ (b >> 4)) & 0x0F] ^ (crc >> 4);
28985|  38.7M|  }
28986|   152k|  return ~crc;
28987|   152k|}
mg_crc16:
28989|  3.03k|uint16_t mg_crc16(uint16_t crc, const char *buf, size_t len) {
28990|  3.03k|  static const uint16_t crclut[16] = {
28991|       |      // table for polynomial 0x8408 (reflected)
28992|  3.03k|      0x0000, 0x1081, 0x2102, 0x3183, 0x4204, 0x5285, 0x6306, 0x7387,
28993|  3.03k|      0x8408, 0x9489, 0xA50A, 0xB58B, 0xC60C, 0xD68D, 0xE70E, 0xF78F};
28994|  3.03k|  unsigned int c = (unsigned int) ~crc & 0xffff;
28995|   249k|  while (len--) {
  ------------------
  |  Branch (28995:10): [True: 246k, False: 3.03k]
  ------------------
28996|   246k|    uint8_t b = *(uint8_t *) buf++;
28997|   246k|    c = crclut[(c ^ b) & 0x0F] ^ (c >> 4);
28998|   246k|    c = crclut[(c ^ (b >> 4)) & 0x0F] ^ (c >> 4);
28999|   246k|  }
29000|  3.03k|  return (uint16_t) ~c;
29001|  3.03k|}
mg_path_is_sane:
29040|   208k|bool mg_path_is_sane(const struct mg_str path) {
29041|   208k|  const char *s = path.buf;
29042|   208k|  size_t n = path.len;
29043|   208k|  if (n == 0 || path.buf[0] == '\0') return true;
  ------------------
  |  Branch (29043:7): [True: 0, False: 208k]
  |  Branch (29043:17): [True: 0, False: 208k]
  ------------------
29044|   208k|  if (s[0] == '~') return false;  // Starts with ~
  ------------------
  |  Branch (29044:7): [True: 0, False: 208k]
  ------------------
29045|   208k|  if (s[0] == '.' && n > 1 && s[1] == '.')
  ------------------
  |  Branch (29045:7): [True: 208k, False: 0]
  |  Branch (29045:22): [True: 208k, False: 0]
  |  Branch (29045:31): [True: 0, False: 208k]
  ------------------
29046|      0|    return false;  // Starts with ..
29047|  3.37M|  for (; n > 0 && s[0] != '\0'; s++, n--) {
  ------------------
  |  Branch (29047:10): [True: 3.16M, False: 208k]
  |  Branch (29047:19): [True: 3.16M, False: 0]
  ------------------
29048|  3.16M|    if ((s[0] == '/' || s[0] == '\\') && n >= 2 && s[1] == '.' && n > 2 &&
  ------------------
  |  Branch (29048:10): [True: 2.80M, False: 352k]
  |  Branch (29048:25): [True: 3.69k, False: 348k]
  |  Branch (29048:42): [True: 2.62M, False: 187k]
  |  Branch (29048:52): [True: 17.9k, False: 2.60M]
  |  Branch (29048:67): [True: 17.5k, False: 405]
  ------------------
29049|  17.5k|        s[2] == '.')
  ------------------
  |  Branch (29049:9): [True: 273, False: 17.2k]
  ------------------
29050|    273|      return false;  // Subdir starts with ..
29051|  3.16M|  }
29052|   208k|  if (n > 0) return false;  // embedded nul (terminator not counted in len)
  ------------------
  |  Branch (29052:7): [True: 0, False: 208k]
  ------------------
29053|   208k|  return true;
29054|   208k|}
mg_millis:
29058|  11.3k|uint64_t mg_millis(void) {
29059|       |#if MG_ARCH == MG_ARCH_ESP32 || MG_ENABLE_FREERTOS
29060|       |  return xTaskGetTickCount() * portTICK_PERIOD_MS;
29061|       |#elif MG_ARCH == MG_ARCH_THREADX
29062|       |  return tx_time_get() * (1000 /* MS per SEC */ / TX_TIMER_TICKS_PER_SECOND);
29063|       |#elif MG_ARCH == MG_ARCH_TIRTOS
29064|       |  return (uint64_t) Clock_getTicks();
29065|       |#elif MG_ARCH == MG_ARCH_ZEPHYR
29066|       |  return (uint64_t) k_uptime_get();
29067|       |#elif MG_ARCH == MG_ARCH_CMSIS_RTOS1
29068|       |  return (uint64_t) rt_time_get();
29069|       |#elif MG_ARCH == MG_ARCH_CMSIS_RTOS2
29070|       |  return (uint64_t) ((osKernelGetTickCount() * 1000) / osKernelGetTickFreq());
29071|       |#elif MG_ARCH == MG_ARCH_RTTHREAD
29072|       |  return (uint64_t) ((rt_tick_get() * 1000) / RT_TICK_PER_SECOND);
29073|       |#elif MG_ARCH == MG_ARCH_WIN32
29074|       |  return GetTickCount();
29075|       |#elif MG_ARCH == MG_ARCH_PICOSDK
29076|       |  return time_us_64() / 1000;
29077|       |#elif MG_ARCH == MG_ARCH_CUBE
29078|       |  return (uint64_t) HAL_GetTick();
29079|       |#elif MG_ARCH == MG_ARCH_UNIX && defined(__APPLE__)
29080|       |  // Apple CLOCK_MONOTONIC_RAW is equivalent to CLOCK_BOOTTIME on linux
29081|       |  // Apple CLOCK_UPTIME_RAW is equivalent to CLOCK_MONOTONIC_RAW on linux
29082|       |  return clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1000000;
29083|       |#elif MG_ARCH == MG_ARCH_UNIX
29084|       |  struct timespec ts = {0, 0};
29085|       |  // See #1615 - prefer monotonic clock
29086|  11.3k|#if defined(CLOCK_MONOTONIC_RAW)
29087|       |  // Raw hardware-based time that is not subject to NTP adjustment
29088|  11.3k|  clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
29089|       |#elif defined(CLOCK_MONOTONIC)
29090|       |  // Affected by the incremental adjustments performed by adjtime and NTP
29091|       |  clock_gettime(CLOCK_MONOTONIC, &ts);
29092|       |#else
29093|       |  // Affected by discontinuous jumps in the system time and by the incremental
29094|       |  // adjustments performed by adjtime and NTP
29095|       |  clock_gettime(CLOCK_REALTIME, &ts);
29096|       |#endif
29097|  11.3k|  return ((uint64_t) ts.tv_sec * 1000 + (uint64_t) ts.tv_nsec / 1000000);
29098|       |#elif defined(ARDUINO)
29099|       |  return (uint64_t) millis();
29100|       |#else
29101|       |  return (uint64_t) (time(NULL) * 1000);
29102|       |#endif
29103|  11.3k|}
mg_ntohs:
29107|  95.6k|uint16_t mg_ntohs(uint16_t net) {
29108|  95.6k|  return MG_LOAD_BE16(&net);
  ------------------
  |  | 2040|  95.6k|  ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 2033|  95.6k|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  |                 ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
  |  |  ------------------
  |  |  |  | 2033|  95.6k|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  ------------------
29109|  95.6k|}
mg_ntohl:
29111|  12.2k|uint32_t mg_ntohl(uint32_t net) {
29112|  12.2k|  return MG_LOAD_BE32(&net);
  ------------------
  |  | 2045|  12.2k|  ((uint32_t) (((uint32_t) MG_U8P(p)[0] << 24U) | \
  |  |  ------------------
  |  |  |  | 2033|  12.2k|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2046|  12.2k|               ((uint32_t) MG_U8P(p)[1] << 16U) | \
  |  |  ------------------
  |  |  |  | 2033|  12.2k|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  | 2047|  12.2k|               ((uint32_t) MG_U8P(p)[2] << 8U) | MG_U8P(p)[3]))
  |  |  ------------------
  |  |  |  | 2033|  12.2k|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  |  |                              ((uint32_t) MG_U8P(p)[2] << 8U) | MG_U8P(p)[3]))
  |  |  ------------------
  |  |  |  | 2033|  12.2k|#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
  |  |  ------------------
  ------------------
29113|  12.2k|}
mg_calloc:
29126|  45.9k|void *mg_calloc(size_t count, size_t size) {
29127|  45.9k|  return calloc(count, size);
29128|  45.9k|}
mg_free:
29130|  73.8k|void mg_free(void *ptr) {
29131|  73.8k|  free(ptr);
29132|  73.8k|}
fuzz.c:_ZL23mg_base64_encode_singlei:
   27|   254M|static int mg_base64_encode_single(int c) {
   28|   254M|  if (c < 26) {
  ------------------
  |  Branch (28:7): [True: 156M, False: 98.2M]
  ------------------
   29|   156M|    return c + 'A';
   30|   156M|  } else if (c < 52) {
  ------------------
  |  Branch (30:14): [True: 79.7M, False: 18.5M]
  ------------------
   31|  79.7M|    return c - 26 + 'a';
   32|  79.7M|  } else if (c < 62) {
  ------------------
  |  Branch (32:14): [True: 16.1M, False: 2.39M]
  ------------------
   33|  16.1M|    return c - 52 + '0';
   34|  16.1M|  } else {
   35|  2.39M|    return c == 62 ? '+' : '/';
  ------------------
  |  Branch (35:12): [True: 180k, False: 2.21M]
  ------------------
   36|  2.39M|  }
   37|   254M|}
fuzz.c:_ZL23mg_base64_decode_singlei:
   57|  2.38M|static int mg_base64_decode_single(int c) {
   58|  2.38M|  return base64_decode_single(c, '+', '/');
   59|  2.38M|}
fuzz.c:_ZL20base64_decode_singleicc:
   39|  2.38M|static int base64_decode_single(int c, char plus, char slash) {
   40|  2.38M|  if (c >= 'A' && c <= 'Z') {
  ------------------
  |  Branch (40:7): [True: 24.5k, False: 2.36M]
  |  Branch (40:19): [True: 12.4k, False: 12.1k]
  ------------------
   41|  12.4k|    return c - 'A';
   42|  2.37M|  } else if (c >= 'a' && c <= 'z') {
  ------------------
  |  Branch (42:14): [True: 11.1k, False: 2.36M]
  |  Branch (42:26): [True: 10.3k, False: 735]
  ------------------
   43|  10.3k|    return c + 26 - 'a';
   44|  2.36M|  } else if (c >= '0' && c <= '9') {
  ------------------
  |  Branch (44:14): [True: 2.34M, False: 16.3k]
  |  Branch (44:26): [True: 2.34M, False: 2.87k]
  ------------------
   45|  2.34M|    return c + 52 - '0';
   46|  2.34M|  } else if (c == plus) {
  ------------------
  |  Branch (46:14): [True: 2.04k, False: 17.1k]
  ------------------
   47|  2.04k|    return 62;
   48|  17.1k|  } else if (c == slash) {
  ------------------
  |  Branch (48:14): [True: 4.02k, False: 13.1k]
  ------------------
   49|  4.02k|    return 63;
   50|  13.1k|  } else if (c == '=') {
  ------------------
  |  Branch (50:14): [True: 539, False: 12.5k]
  ------------------
   51|    539|    return 64;
   52|  12.5k|  } else {
   53|  12.5k|    return -1;
   54|  12.5k|  }
   55|  2.38M|}
fuzz.c:_ZL17mg_dns_parse_namePKhmmPcm:
 1892|    914|                                char *dst, size_t dstlen) {
 1893|    914|  return mg_dns_parse_name_depth(s, n, ofs, dst, dstlen, 0, 0);
 1894|    914|}
fuzz.c:_ZL23mg_dns_parse_name_depthPKhmmPcmmi:
 1856|  1.51k|                                      int depth) {
 1857|  1.51k|  size_t i = 0;
 1858|  1.51k|  if (tolen > 0 && depth == 0) to[0] = '\0';
  ------------------
  |  Branch (1858:7): [True: 604, False: 915]
  |  Branch (1858:20): [True: 360, False: 244]
  ------------------
 1859|  1.51k|  if (depth > 5) return 0;
  ------------------
  |  Branch (1859:7): [True: 13, False: 1.50k]
  ------------------
 1860|       |  // MG_INFO(("ofs %lx %x %x", (unsigned long) ofs, s[ofs], s[ofs + 1]));
 1861|  4.79k|  while (ofs + i + 1 < len) {
  ------------------
  |  Branch (1861:10): [True: 4.73k, False: 61]
  ------------------
 1862|  4.73k|    size_t n = s[ofs + i];
 1863|  4.73k|    if (n == 0) {
  ------------------
  |  Branch (1863:9): [True: 453, False: 4.28k]
  ------------------
 1864|    453|      i++;
 1865|    453|      break;
 1866|    453|    }
 1867|  4.28k|    if (n & 0xc0) {
  ------------------
  |  Branch (1867:9): [True: 959, False: 3.32k]
  ------------------
 1868|    959|      size_t ptr = (((n & 0x3f) << 8) | s[ofs + i + 1]);  // 12 is hdr len
 1869|       |      // MG_INFO(("PTR %lx", (unsigned long) ptr));
 1870|    959|      if (ptr + 1 < len && (s[ptr] & 0xc0) == 0 &&
  ------------------
  |  Branch (1870:11): [True: 659, False: 300]
  |  Branch (1870:28): [True: 605, False: 54]
  ------------------
 1871|    605|          mg_dns_parse_name_depth(s, len, ptr, to, tolen, j, depth + 1) == 0)
  ------------------
  |  Branch (1871:11): [True: 88, False: 517]
  ------------------
 1872|     88|        return 0;
 1873|    871|      i += 2;
 1874|    871|      break;
 1875|    959|    }
 1876|  3.32k|    if (ofs + i + n + 1 >= len) return 0;
  ------------------
  |  Branch (1876:9): [True: 33, False: 3.29k]
  ------------------
 1877|  3.29k|    if (j > 0) {
  ------------------
  |  Branch (1877:9): [True: 2.96k, False: 333]
  ------------------
 1878|  2.96k|      if (j < tolen) to[j] = '.';
  ------------------
  |  Branch (1878:11): [True: 867, False: 2.09k]
  ------------------
 1879|  2.96k|      j++;
 1880|  2.96k|    }
 1881|  3.29k|    if (j + n < tolen) memcpy(&to[j], &s[ofs + i + 1], n);
  ------------------
  |  Branch (1881:9): [True: 1.00k, False: 2.29k]
  ------------------
 1882|  3.29k|    j += n;
 1883|  3.29k|    i += n + 1;
 1884|  3.29k|    if (j < tolen) to[j] = '\0';  // Zero-terminate this chunk
  ------------------
  |  Branch (1884:9): [True: 1.00k, False: 2.29k]
  ------------------
 1885|       |    // MG_INFO(("--> [%s]", to));
 1886|  3.29k|  }
 1887|  1.38k|  if (tolen > 0) to[tolen - 1] = '\0';  // Make sure it is nul-term
  ------------------
  |  Branch (1887:7): [True: 604, False: 781]
  ------------------
 1888|  1.38k|  return i;
 1889|  1.50k|}
fuzz.c:_ZL8is_digiti:
 2774|  1.48M|static bool is_digit(int c) {
 2775|  1.48M|  return c >= '0' && c <= '9';
  ------------------
  |  Branch (2775:10): [True: 1.26M, False: 218k]
  |  Branch (2775:22): [True: 420k, False: 841k]
  ------------------
 2776|  1.48M|}
fuzz.c:_ZL6mg_lldPclbb:
 2881|   420k|static size_t mg_lld(char *buf, int64_t val, bool is_signed, bool is_hex) {
 2882|   420k|  const char *letters = "0123456789abcdef";
 2883|   420k|  uint64_t v = (uint64_t) val;
 2884|   420k|  size_t s = 0, n, i;
 2885|   420k|  if (is_signed && val < 0) buf[s++] = '-', v = (uint64_t) (-val);
  ------------------
  |  Branch (2885:7): [True: 210k, False: 210k]
  |  Branch (2885:20): [True: 0, False: 210k]
  ------------------
 2886|       |  // This loop prints a number in reverse order. I guess this is because we
 2887|       |  // write numbers from right to left: least significant digit comes last.
 2888|       |  // Maybe because we use Arabic numbers, and Arabs write RTL?
 2889|   420k|  if (is_hex) {
  ------------------
  |  Branch (2889:7): [True: 0, False: 420k]
  ------------------
 2890|      0|    for (n = 0; v; v >>= 4) buf[s + n++] = letters[v & 15];
  ------------------
  |  Branch (2890:17): [True: 0, False: 0]
  ------------------
 2891|   420k|  } else {
 2892|  1.47M|    for (n = 0; v; v /= 10) buf[s + n++] = letters[v % 10];
  ------------------
  |  Branch (2892:17): [True: 1.05M, False: 420k]
  ------------------
 2893|   420k|  }
 2894|       |  // Reverse a string
 2895|   841k|  for (i = 0; i < n / 2; i++) {
  ------------------
  |  Branch (2895:15): [True: 420k, False: 420k]
  ------------------
 2896|   420k|    char t = buf[s + i];
 2897|   420k|    buf[s + i] = buf[s + n - i - 1], buf[s + n - i - 1] = t;
 2898|   420k|  }
 2899|   420k|  if (val == 0) buf[n++] = '0';  // Handle special case
  ------------------
  |  Branch (2899:7): [True: 0, False: 420k]
  ------------------
 2900|   420k|  return n + s;
 2901|   420k|}
fuzz.c:_ZL4scpyPFvcPvES_Pcm:
 2904|  3.16M|                   size_t len) {
 2905|  3.16M|  size_t i = 0;
 2906|  8.03M|  while (i < len && buf[i] != '\0') out(buf[i++], ptr);
  ------------------
  |  Branch (2906:10): [True: 4.87M, False: 3.16M]
  |  Branch (2906:21): [True: 4.87M, False: 0]
  ------------------
 2907|  3.16M|  return i;
 2908|  3.16M|}
fuzz.c:_ZL6p_statPKcPmPl:
 3379|   574k|static int p_stat(const char *path, size_t *size, time_t *mtime) {
 3380|       |#if !defined(S_ISDIR)
 3381|       |  MG_ERROR(("stat() API is not supported. %p %p %p", path, size, mtime));
 3382|       |  return 0;
 3383|       |#else
 3384|       |#if MG_ARCH == MG_ARCH_WIN32
 3385|       |  struct _stati64 st;
 3386|       |  wchar_t tmp[MG_PATH_MAX];
 3387|       |  MultiByteToWideChar(CP_UTF8, 0, path, -1, tmp, sizeof(tmp) / sizeof(tmp[0]));
 3388|       |  if (_wstati64(tmp, &st) != 0) return 0;
 3389|       |  // If path is a symlink, windows reports 0 in st.st_size.
 3390|       |  // Get a real file size by opening it and jumping to the end
 3391|       |  if (st.st_size == 0 && (st.st_mode & _S_IFREG)) {
 3392|       |    FILE *fp = _wfopen(tmp, L"rb");
 3393|       |    if (fp != NULL) {
 3394|       |      fseek(fp, 0, SEEK_END);
 3395|       |      if (ftell(fp) > 0) st.st_size = ftell(fp);  // Use _ftelli64 on win10+
 3396|       |      fclose(fp);
 3397|       |    }
 3398|       |  }
 3399|       |#else
 3400|   574k|  struct MG_STAT_STRUCT st;
 3401|   574k|  if (MG_STAT_FUNC(path, &st) != 0) return 0;
  ------------------
  |  | 3372|   574k|#define MG_STAT_FUNC stat
  ------------------
  |  Branch (3401:7): [True: 569k, False: 5.44k]
  ------------------
 3402|  5.44k|#endif
 3403|  5.44k|  if (size) *size = (size_t) st.st_size;
  ------------------
  |  Branch (3403:7): [True: 0, False: 5.44k]
  ------------------
 3404|  5.44k|  if (mtime) *mtime = st.st_mtime;
  ------------------
  |  Branch (3404:7): [True: 0, False: 5.44k]
  ------------------
 3405|  5.44k|  return MG_FS_READ | MG_FS_WRITE | (S_ISDIR(st.st_mode) ? MG_FS_DIR : 0);
  ------------------
  |  Branch (3405:38): [True: 5.44k, False: 0]
  ------------------
 3406|   574k|#endif
 3407|   574k|}
fuzz.c:_ZL6p_openPKci:
 3540|  21.8k|static void *p_open(const char *path, int flags) {
 3541|       |#if MG_ARCH == MG_ARCH_WIN32
 3542|       |  const char *mode = flags == MG_FS_READ    ? "rb"
 3543|       |                     : (flags & MG_FS_EXCL) ? "wxb"
 3544|       |                                            : "a+b";
 3545|       |  wchar_t b1[MG_PATH_MAX], b2[10];
 3546|       |  MultiByteToWideChar(CP_UTF8, 0, path, -1, b1, sizeof(b1) / sizeof(b1[0]));
 3547|       |  MultiByteToWideChar(CP_UTF8, 0, mode, -1, b2, sizeof(b2) / sizeof(b2[0]));
 3548|       |  return (void *) _wfopen(b1, b2);
 3549|       |#else
 3550|  21.8k|  const char *mode = flags == MG_FS_READ    ? "rbe"
  ------------------
  |  Branch (3550:22): [True: 21.8k, False: 0]
  ------------------
 3551|  21.8k|                     : (flags & MG_FS_EXCL) ? "wxbe"
  ------------------
  |  Branch (3551:24): [True: 0, False: 0]
  ------------------
 3552|      0|                                            : "a+be"; // e for CLOSEXEC
 3553|  21.8k|  return (void *) fopen(path, mode);
 3554|  21.8k|#endif
 3555|  21.8k|}
fuzz.c:_ZL11mg_ncasecmpPKcS0_m:
 3776|   857k|static int mg_ncasecmp(const char *s1, const char *s2, size_t len) {
 3777|   857k|  int diff = 0;
 3778|  3.03M|  if (len > 0) do {
  ------------------
  |  Branch (3778:7): [True: 857k, False: 0]
  ------------------
 3779|  3.03M|      int c = *s1++, d = *s2++;
 3780|  3.03M|      if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
  ------------------
  |  Branch (3780:11): [True: 2.37M, False: 659k]
  |  Branch (3780:23): [True: 938k, False: 1.43M]
  ------------------
 3781|  3.03M|      if (d >= 'A' && d <= 'Z') d += 'a' - 'A';
  ------------------
  |  Branch (3781:11): [True: 2.39M, False: 644k]
  |  Branch (3781:23): [True: 2.10M, False: 285k]
  ------------------
 3782|  3.03M|      diff = c - d;
 3783|  3.03M|    } while (diff == 0 && s1[-1] != '\0' && --len > 0);
  ------------------
  |  Branch (3783:14): [True: 2.43M, False: 606k]
  |  Branch (3783:27): [True: 2.43M, False: 0]
  |  Branch (3783:45): [True: 2.17M, False: 250k]
  ------------------
 3784|   857k|  return diff;
 3785|   857k|}
fuzz.c:_ZL3isxi:
 3922|   100k|static bool isx(int c) {
 3923|   100k|  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
  ------------------
  |  Branch (3923:11): [True: 96.4k, False: 3.81k]
  |  Branch (3923:23): [True: 4.08k, False: 92.4k]
  |  Branch (3923:37): [True: 83.8k, False: 12.4k]
  |  Branch (3923:49): [True: 82.4k, False: 1.33k]
  ------------------
 3924|  13.7k|         (c >= 'A' && c <= 'F');
  ------------------
  |  Branch (3924:11): [True: 9.26k, False: 4.47k]
  |  Branch (3924:23): [True: 7.91k, False: 1.35k]
  ------------------
 3925|   100k|}
fuzz.c:_ZL4isokh:
 3950|   211M|static bool isok(uint8_t c) {
 3951|   211M|  return c == '\n' || c == '\r' || c == '\t' || c >= ' ';
  ------------------
  |  Branch (3951:10): [True: 592k, False: 210M]
  |  Branch (3951:23): [True: 21.7k, False: 210M]
  |  Branch (3951:36): [True: 92.1k, False: 210M]
  |  Branch (3951:49): [True: 210M, False: 3.29k]
  ------------------
 3952|   211M|}
fuzz.c:_ZL4clenPKcS0_:
 3979|  73.5M|static size_t clen(const char *s, const char *end) {
 3980|  73.5M|  const unsigned char *u = (unsigned char *) s, c = *u;
 3981|  73.5M|  long n = (long) (end - s);
 3982|  73.5M|  if (c > ' ' && c <= '~') return 1;  // Usual ascii printed char
  ------------------
  |  Branch (3982:7): [True: 73.1M, False: 423k]
  |  Branch (3982:18): [True: 73.0M, False: 32.2k]
  ------------------
 3983|   455k|  if ((c & 0xe0) == 0xc0 && n > 1 && vcb(u[1])) return 2;  // 2-byte UTF8
  ------------------
  |  Branch (3983:7): [True: 12.7k, False: 442k]
  |  Branch (3983:29): [True: 12.7k, False: 0]
  |  Branch (3983:38): [True: 5.50k, False: 7.22k]
  ------------------
 3984|   450k|  if ((c & 0xf0) == 0xe0 && n > 2 && vcb(u[1]) && vcb(u[2])) return 3;
  ------------------
  |  Branch (3984:7): [True: 7.50k, False: 442k]
  |  Branch (3984:29): [True: 7.50k, False: 0]
  |  Branch (3984:38): [True: 6.67k, False: 832]
  |  Branch (3984:51): [True: 6.09k, False: 579]
  ------------------
 3985|   444k|  if ((c & 0xf8) == 0xf0 && n > 3 && vcb(u[1]) && vcb(u[2]) && vcb(u[3]))
  ------------------
  |  Branch (3985:7): [True: 9.05k, False: 435k]
  |  Branch (3985:29): [True: 8.31k, False: 737]
  |  Branch (3985:38): [True: 6.52k, False: 1.79k]
  |  Branch (3985:51): [True: 4.94k, False: 1.57k]
  |  Branch (3985:64): [True: 3.65k, False: 1.28k]
  ------------------
 3986|  3.65k|    return 4;
 3987|   440k|  return 0;
 3988|   444k|}
fuzz.c:_ZL3vcbh:
 3974|  46.6k|static bool vcb(uint8_t c) {
 3975|  46.6k|  return (c & 0xc0) == 0x80;
 3976|  46.6k|}
fuzz.c:_ZL8skiptornPKcS0_P6mg_str:
 3991|   270k|static const char *skiptorn(const char *s, const char *end, struct mg_str *v) {
 3992|   270k|  v->buf = (char *) s;
 3993|  58.1M|  while (s < end && s[0] != '\n' && s[0] != '\r') s++, v->len++;  // To newline
  ------------------
  |  Branch (3993:10): [True: 58.1M, False: 0]
  |  Branch (3993:21): [True: 57.8M, False: 256k]
  |  Branch (3993:37): [True: 57.8M, False: 13.3k]
  ------------------
 3994|   270k|  if (s >= end || (s[0] == '\r' && s[1] != '\n')) return NULL;    // Stray \r
  ------------------
  |  Branch (3994:7): [True: 0, False: 270k]
  |  Branch (3994:20): [True: 13.3k, False: 256k]
  |  Branch (3994:36): [True: 261, False: 13.1k]
  ------------------
 3995|   269k|  if (s < end && s[0] == '\r') s++;                               // Skip \r
  ------------------
  |  Branch (3995:7): [True: 269k, False: 0]
  |  Branch (3995:18): [True: 13.1k, False: 256k]
  ------------------
 3996|   269k|  if (s >= end || *s++ != '\n') return NULL;                      // Skip \n
  ------------------
  |  Branch (3996:7): [True: 0, False: 269k]
  |  Branch (3996:19): [True: 0, False: 269k]
  ------------------
 3997|   269k|  return s;
 3998|   269k|}
fuzz.c:_ZL21mg_http_parse_headersPKcS0_P14mg_http_headerm:
 4001|   218k|                                  struct mg_http_header *h, size_t max_hdrs) {
 4002|   218k|  size_t i, n;
 4003|   218k|  int cl_count = 0, te_count = 0, auth_count = 0;
 4004|   218k|  int conn_count = 0, cookie_count = 0;
 4005|   269k|  for (i = 0; i < max_hdrs; i++) {
  ------------------
  |  Branch (4005:15): [True: 268k, False: 429]
  ------------------
 4006|   268k|    struct mg_str k = {NULL, 0}, v = {NULL, 0};
 4007|   268k|    if (s >= end) return false;
  ------------------
  |  Branch (4007:9): [True: 0, False: 268k]
  ------------------
 4008|   268k|    if (s[0] == '\n' || (s[0] == '\r' && s[1] == '\n')) break;
  ------------------
  |  Branch (4008:9): [True: 216k, False: 51.7k]
  |  Branch (4008:26): [True: 1.07k, False: 50.6k]
  |  Branch (4008:42): [True: 1.06k, False: 11]
  ------------------
 4009|  50.6k|    k.buf = (char *) s;
 4010|  39.9M|    while (s < end && s[0] != ':' && (n = clen(s, end)) > 0) s += n, k.len += n;
  ------------------
  |  Branch (4010:12): [True: 39.9M, False: 0]
  |  Branch (4010:23): [True: 39.9M, False: 50.3k]
  |  Branch (4010:38): [True: 39.9M, False: 347]
  ------------------
 4011|  50.6k|    if (k.len == 0) return false;                     // Empty name
  ------------------
  |  Branch (4011:9): [True: 76, False: 50.6k]
  ------------------
 4012|  50.6k|    if (s >= end || clen(s, end) == 0) return false;  // Invalid UTF-8
  ------------------
  |  Branch (4012:9): [True: 0, False: 50.6k]
  |  Branch (4012:21): [True: 279, False: 50.3k]
  ------------------
 4013|  50.3k|    if (*s++ != ':') return false;  // Invalid, not followed by :
  ------------------
  |  Branch (4013:9): [True: 0, False: 50.3k]
  ------------------
 4014|       |    // if (clen(s, end) == 0) return false;        // Invalid UTF-8
 4015|  68.7k|    while (s < end && (s[0] == ' ' || s[0] == '\t')) s++;  // Skip spaces
  ------------------
  |  Branch (4015:12): [True: 68.7k, False: 0]
  |  Branch (4015:24): [True: 18.0k, False: 50.6k]
  |  Branch (4015:39): [True: 356, False: 50.3k]
  ------------------
 4016|  50.3k|    if ((s = skiptorn(s, end, &v)) == NULL) return false;
  ------------------
  |  Branch (4016:9): [True: 3, False: 50.3k]
  ------------------
 4017|  51.1k|    while (v.len > 0 && (v.buf[v.len - 1] == ' ' || v.buf[v.len - 1] == '\t')) {
  ------------------
  |  Branch (4017:12): [True: 29.1k, False: 21.9k]
  |  Branch (4017:26): [True: 404, False: 28.7k]
  |  Branch (4017:53): [True: 426, False: 28.3k]
  ------------------
 4018|    830|      v.len--;  // Trim spaces
 4019|    830|    }
 4020|       |    // detect duplicated headers -> discard
 4021|  50.3k|    if (((mg_strcasecmp(k, mg_str("Content-Length")) == 0) &&
  ------------------
  |  | 1524|  50.3k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4021:10): [True: 1.88k, False: 48.4k]
  ------------------
 4022|  1.88k|         (++cl_count > 1)) ||
  ------------------
  |  Branch (4022:10): [True: 3, False: 1.87k]
  ------------------
 4023|  50.3k|        ((mg_strcasecmp(k, mg_str("Transfer-Encoding")) == 0) &&
  ------------------
  |  | 1524|  50.3k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4023:10): [True: 11.0k, False: 39.2k]
  ------------------
 4024|  11.0k|         (++te_count > 1)) ||
  ------------------
  |  Branch (4024:10): [True: 4, False: 11.0k]
  ------------------
 4025|  50.3k|        ((mg_strcasecmp(k, mg_str("Authorization")) == 0) &&
  ------------------
  |  | 1524|  50.3k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4025:10): [True: 0, False: 50.3k]
  ------------------
 4026|      0|         (++auth_count > 1)) ||
  ------------------
  |  Branch (4026:10): [True: 0, False: 0]
  ------------------
 4027|  50.3k|        ((mg_strcasecmp(k, mg_str("Cookie")) == 0) && (++cookie_count > 1)) ||
  ------------------
  |  | 1524|  50.3k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4027:10): [True: 0, False: 50.3k]
  |  Branch (4027:55): [True: 0, False: 0]
  ------------------
 4028|  50.3k|        ((mg_strcasecmp(k, mg_str("Connection")) == 0) && (++conn_count > 1)))
  ------------------
  |  | 1524|  50.3k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4028:10): [True: 0, False: 50.3k]
  |  Branch (4028:59): [True: 0, False: 0]
  ------------------
 4029|      7|      return false;
 4030|       |    // MG_INFO(("--HH [%.*s] [%.*s]", (int) k.len, k.buf, (int) v.len, v.buf));
 4031|  50.3k|    h[i].name = k, h[i].value = v;  // Success. Assign values
 4032|  50.3k|  }
 4033|   218k|  return true;
 4034|   218k|}
fuzz.c:_ZL23mg_http_status_code_stri:
 4145|   210k|static const char *mg_http_status_code_str(int status_code) {
 4146|   210k|  switch (status_code) {
 4147|      0|    case 100: return "Continue";
  ------------------
  |  Branch (4147:5): [True: 0, False: 210k]
  ------------------
 4148|      0|    case 101: return "Switching Protocols";
  ------------------
  |  Branch (4148:5): [True: 0, False: 210k]
  ------------------
 4149|      0|    case 102: return "Processing";
  ------------------
  |  Branch (4149:5): [True: 0, False: 210k]
  ------------------
 4150|      0|    case 200: return "OK";
  ------------------
  |  Branch (4150:5): [True: 0, False: 210k]
  ------------------
 4151|      0|    case 201: return "Created";
  ------------------
  |  Branch (4151:5): [True: 0, False: 210k]
  ------------------
 4152|      0|    case 202: return "Accepted";
  ------------------
  |  Branch (4152:5): [True: 0, False: 210k]
  ------------------
 4153|      0|    case 203: return "Non-authoritative Information";
  ------------------
  |  Branch (4153:5): [True: 0, False: 210k]
  ------------------
 4154|      0|    case 204: return "No Content";
  ------------------
  |  Branch (4154:5): [True: 0, False: 210k]
  ------------------
 4155|      0|    case 205: return "Reset Content";
  ------------------
  |  Branch (4155:5): [True: 0, False: 210k]
  ------------------
 4156|      0|    case 206: return "Partial Content";
  ------------------
  |  Branch (4156:5): [True: 0, False: 210k]
  ------------------
 4157|      0|    case 207: return "Multi-Status";
  ------------------
  |  Branch (4157:5): [True: 0, False: 210k]
  ------------------
 4158|      0|    case 208: return "Already Reported";
  ------------------
  |  Branch (4158:5): [True: 0, False: 210k]
  ------------------
 4159|      0|    case 226: return "IM Used";
  ------------------
  |  Branch (4159:5): [True: 0, False: 210k]
  ------------------
 4160|      0|    case 300: return "Multiple Choices";
  ------------------
  |  Branch (4160:5): [True: 0, False: 210k]
  ------------------
 4161|      0|    case 301: return "Moved Permanently";
  ------------------
  |  Branch (4161:5): [True: 0, False: 210k]
  ------------------
 4162|      0|    case 302: return "Found";
  ------------------
  |  Branch (4162:5): [True: 0, False: 210k]
  ------------------
 4163|      0|    case 303: return "See Other";
  ------------------
  |  Branch (4163:5): [True: 0, False: 210k]
  ------------------
 4164|      0|    case 304: return "Not Modified";
  ------------------
  |  Branch (4164:5): [True: 0, False: 210k]
  ------------------
 4165|      0|    case 305: return "Use Proxy";
  ------------------
  |  Branch (4165:5): [True: 0, False: 210k]
  ------------------
 4166|      0|    case 307: return "Temporary Redirect";
  ------------------
  |  Branch (4166:5): [True: 0, False: 210k]
  ------------------
 4167|      0|    case 308: return "Permanent Redirect";
  ------------------
  |  Branch (4167:5): [True: 0, False: 210k]
  ------------------
 4168|  6.08k|    case 400: return "Bad Request";
  ------------------
  |  Branch (4168:5): [True: 6.08k, False: 204k]
  ------------------
 4169|      0|    case 401: return "Unauthorized";
  ------------------
  |  Branch (4169:5): [True: 0, False: 210k]
  ------------------
 4170|      0|    case 402: return "Payment Required";
  ------------------
  |  Branch (4170:5): [True: 0, False: 210k]
  ------------------
 4171|   182k|    case 403: return "Forbidden";
  ------------------
  |  Branch (4171:5): [True: 182k, False: 27.6k]
  ------------------
 4172|  21.5k|    case 404: return "Not Found";
  ------------------
  |  Branch (4172:5): [True: 21.5k, False: 188k]
  ------------------
 4173|      0|    case 405: return "Method Not Allowed";
  ------------------
  |  Branch (4173:5): [True: 0, False: 210k]
  ------------------
 4174|      0|    case 406: return "Not Acceptable";
  ------------------
  |  Branch (4174:5): [True: 0, False: 210k]
  ------------------
 4175|      0|    case 407: return "Proxy Authentication Required";
  ------------------
  |  Branch (4175:5): [True: 0, False: 210k]
  ------------------
 4176|      0|    case 408: return "Request Timeout";
  ------------------
  |  Branch (4176:5): [True: 0, False: 210k]
  ------------------
 4177|      0|    case 409: return "Conflict";
  ------------------
  |  Branch (4177:5): [True: 0, False: 210k]
  ------------------
 4178|      0|    case 410: return "Gone";
  ------------------
  |  Branch (4178:5): [True: 0, False: 210k]
  ------------------
 4179|      0|    case 411: return "Length Required";
  ------------------
  |  Branch (4179:5): [True: 0, False: 210k]
  ------------------
 4180|      0|    case 412: return "Precondition Failed";
  ------------------
  |  Branch (4180:5): [True: 0, False: 210k]
  ------------------
 4181|      0|    case 413: return "Payload Too Large";
  ------------------
  |  Branch (4181:5): [True: 0, False: 210k]
  ------------------
 4182|      0|    case 414: return "Request-URI Too Long";
  ------------------
  |  Branch (4182:5): [True: 0, False: 210k]
  ------------------
 4183|      0|    case 415: return "Unsupported Media Type";
  ------------------
  |  Branch (4183:5): [True: 0, False: 210k]
  ------------------
 4184|      0|    case 416: return "Requested Range Not Satisfiable";
  ------------------
  |  Branch (4184:5): [True: 0, False: 210k]
  ------------------
 4185|      0|    case 417: return "Expectation Failed";
  ------------------
  |  Branch (4185:5): [True: 0, False: 210k]
  ------------------
 4186|      0|    case 418: return "I'm a teapot";
  ------------------
  |  Branch (4186:5): [True: 0, False: 210k]
  ------------------
 4187|      0|    case 421: return "Misdirected Request";
  ------------------
  |  Branch (4187:5): [True: 0, False: 210k]
  ------------------
 4188|      0|    case 422: return "Unprocessable Entity";
  ------------------
  |  Branch (4188:5): [True: 0, False: 210k]
  ------------------
 4189|      0|    case 423: return "Locked";
  ------------------
  |  Branch (4189:5): [True: 0, False: 210k]
  ------------------
 4190|      0|    case 424: return "Failed Dependency";
  ------------------
  |  Branch (4190:5): [True: 0, False: 210k]
  ------------------
 4191|      0|    case 426: return "Upgrade Required";
  ------------------
  |  Branch (4191:5): [True: 0, False: 210k]
  ------------------
 4192|      0|    case 428: return "Precondition Required";
  ------------------
  |  Branch (4192:5): [True: 0, False: 210k]
  ------------------
 4193|      0|    case 429: return "Too Many Requests";
  ------------------
  |  Branch (4193:5): [True: 0, False: 210k]
  ------------------
 4194|      0|    case 431: return "Request Header Fields Too Large";
  ------------------
  |  Branch (4194:5): [True: 0, False: 210k]
  ------------------
 4195|      0|    case 444: return "Connection Closed Without Response";
  ------------------
  |  Branch (4195:5): [True: 0, False: 210k]
  ------------------
 4196|      0|    case 451: return "Unavailable For Legal Reasons";
  ------------------
  |  Branch (4196:5): [True: 0, False: 210k]
  ------------------
 4197|      0|    case 499: return "Client Closed Request";
  ------------------
  |  Branch (4197:5): [True: 0, False: 210k]
  ------------------
 4198|      0|    case 500: return "Internal Server Error";
  ------------------
  |  Branch (4198:5): [True: 0, False: 210k]
  ------------------
 4199|      0|    case 501: return "Not Implemented";
  ------------------
  |  Branch (4199:5): [True: 0, False: 210k]
  ------------------
 4200|      0|    case 502: return "Bad Gateway";
  ------------------
  |  Branch (4200:5): [True: 0, False: 210k]
  ------------------
 4201|      0|    case 503: return "Service Unavailable";
  ------------------
  |  Branch (4201:5): [True: 0, False: 210k]
  ------------------
 4202|      0|    case 504: return "Gateway Timeout";
  ------------------
  |  Branch (4202:5): [True: 0, False: 210k]
  ------------------
 4203|      0|    case 505: return "HTTP Version Not Supported";
  ------------------
  |  Branch (4203:5): [True: 0, False: 210k]
  ------------------
 4204|      0|    case 506: return "Variant Also Negotiates";
  ------------------
  |  Branch (4204:5): [True: 0, False: 210k]
  ------------------
 4205|      0|    case 507: return "Insufficient Storage";
  ------------------
  |  Branch (4205:5): [True: 0, False: 210k]
  ------------------
 4206|      0|    case 508: return "Loop Detected";
  ------------------
  |  Branch (4206:5): [True: 0, False: 210k]
  ------------------
 4207|      0|    case 510: return "Not Extended";
  ------------------
  |  Branch (4207:5): [True: 0, False: 210k]
  ------------------
 4208|      0|    case 511: return "Network Authentication Required";
  ------------------
  |  Branch (4208:5): [True: 0, False: 210k]
  ------------------
 4209|      0|    case 599: return "Network Connect Timeout Error";
  ------------------
  |  Branch (4209:5): [True: 0, False: 210k]
  ------------------
 4210|      0|    default: return "";
  ------------------
  |  Branch (4210:5): [True: 0, False: 210k]
  ------------------
 4211|   210k|  }
 4212|   210k|}
fuzz.c:_ZL18guess_content_type6mg_strPKc:
 4306|  21.5k|static struct mg_str guess_content_type(struct mg_str path, const char *extra) {
 4307|  21.5k|  struct mg_str entry, k, v, s = mg_str(extra), asterisk = mg_str_n("*", 1);
  ------------------
  |  | 1524|  21.5k|#define mg_str(s) mg_str_s(s)
  ------------------
 4308|  21.5k|  size_t i = 0;
 4309|       |
 4310|       |  // Shrink path to its extension only
 4311|   184k|  while (i < path.len && path.buf[path.len - i - 1] != '.') i++;
  ------------------
  |  Branch (4311:10): [True: 184k, False: 0]
  |  Branch (4311:26): [True: 162k, False: 21.5k]
  ------------------
 4312|  21.5k|  path.buf += path.len - i;
 4313|  21.5k|  path.len = i;
 4314|       |
 4315|       |  // Process user-provided mime type overrides, if any
 4316|  21.5k|  while (mg_span(s, &entry, &s, ',')) {
  ------------------
  |  Branch (4316:10): [True: 0, False: 21.5k]
  ------------------
 4317|      0|    if (mg_span(entry, &k, &v, '=') &&
  ------------------
  |  Branch (4317:9): [True: 0, False: 0]
  ------------------
 4318|      0|        (mg_strcmp(asterisk, k) == 0 || mg_strcmp(path, k) == 0))
  ------------------
  |  Branch (4318:10): [True: 0, False: 0]
  |  Branch (4318:41): [True: 0, False: 0]
  ------------------
 4319|      0|      return v;
 4320|      0|  }
 4321|       |
 4322|       |  // Process built-in mime types
 4323|   684k|  for (i = 0; s_known_types[i].buf != NULL; i += 2) {
  ------------------
  |  Branch (4323:15): [True: 662k, False: 21.3k]
  ------------------
 4324|   662k|    if (mg_strcmp(path, s_known_types[i]) == 0) return s_known_types[i + 1];
  ------------------
  |  Branch (4324:9): [True: 216, False: 662k]
  ------------------
 4325|   662k|  }
 4326|       |
 4327|  21.3k|  return mg_str("text/plain; charset=utf-8");
  ------------------
  |  | 1524|  21.3k|#define mg_str(s) mg_str_s(s)
  ------------------
 4328|  21.5k|}
fuzz.c:_ZL18uri_to_file_statusP13mg_connectionP15mg_http_messageP5mg_fsPKcPcm:
 4526|   214k|                              char *path, size_t path_size) {
 4527|   214k|  int flags, tmp;
 4528|   214k|  size_t n;
 4529|   214k|  if (!uri2path(root_dir, hm->uri, path, path_size)) {
  ------------------
  |  Branch (4529:7): [True: 6.08k, False: 208k]
  ------------------
 4530|  6.08k|    mg_http_reply(c, 400, "", "Invalid path");
 4531|  6.08k|    return -1;
 4532|  6.08k|  }
 4533|   208k|  n = strlen(path);
 4534|   208k|  flags = mg_strcmp(hm->uri, mg_str("/")) == 0 ? MG_FS_DIR
  ------------------
  |  | 1524|   208k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4534:11): [True: 181k, False: 27.0k]
  ------------------
 4535|   208k|                                               : fs->st(path, NULL, NULL);
 4536|   208k|  MG_VERBOSE(("%lu %.*s -> %s %d", c->id, (int) hm->uri.len, hm->uri.buf, path,
  ------------------
  |  | 1826|   208k|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1813|   208k|  do {                      \
  |  |  |  | 1814|   208k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 208k]
  |  |  |  |  ------------------
  |  |  |  | 1815|   208k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 208k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4537|   208k|              flags));
 4538|   208k|  if (flags == 0) {
  ------------------
  |  Branch (4538:7): [True: 21.5k, False: 186k]
  ------------------
 4539|       |    // Do nothing - let's caller decide
 4540|   186k|  } else if ((flags & MG_FS_DIR) && hm->uri.len > 0 &&
  ------------------
  |  Branch (4540:14): [True: 186k, False: 0]
  |  Branch (4540:37): [True: 186k, False: 0]
  ------------------
 4541|   186k|             hm->uri.buf[hm->uri.len - 1] != '/') {
  ------------------
  |  Branch (4541:14): [True: 4.10k, False: 182k]
  ------------------
 4542|  4.10k|    mg_printf(c,
 4543|  4.10k|              "HTTP/1.1 301 Moved\r\n"
 4544|  4.10k|              "Location: %.*s/\r\n"
 4545|  4.10k|              "Content-Length: 0\r\n"
 4546|  4.10k|              "\r\n",
 4547|  4.10k|              (int) hm->uri.len, hm->uri.buf);
 4548|  4.10k|    c->pfn_data = NULL;  // Response done
 4549|  4.10k|    flags = -1;
 4550|   182k|  } else if (flags & MG_FS_DIR) {
  ------------------
  |  Branch (4550:14): [True: 182k, False: 0]
  ------------------
 4551|   182k|    if (((mg_snprintf(path + n, path_size - n, "/" MG_HTTP_INDEX) > 0 &&
  ------------------
  |  | 1300|   182k|#define MG_HTTP_INDEX "index.html"
  ------------------
  |  Branch (4551:11): [True: 182k, False: 0]
  ------------------
 4552|   182k|          (tmp = fs->st(path, NULL, NULL)) != 0) ||
  ------------------
  |  Branch (4552:11): [True: 1, False: 182k]
  ------------------
 4553|   182k|         (mg_snprintf(path + n, path_size - n, "/index.shtml") > 0 &&
  ------------------
  |  Branch (4553:11): [True: 182k, False: 0]
  ------------------
 4554|   182k|          (tmp = fs->st(path, NULL, NULL)) != 0))) {
  ------------------
  |  Branch (4554:11): [True: 0, False: 182k]
  ------------------
 4555|      1|      flags = tmp;
 4556|   182k|    } else if ((mg_snprintf(path + n, path_size - n, "/" MG_HTTP_INDEX ".gz") >
  ------------------
  |  Branch (4556:17): [True: 182k, False: 0]
  ------------------
 4557|   182k|                    0 &&
 4558|   182k|                (tmp = fs->st(path, NULL, NULL)) !=
  ------------------
  |  Branch (4558:17): [True: 0, False: 182k]
  ------------------
 4559|   182k|                    0)) {  // check for gzipped index
 4560|      0|      flags = tmp;
 4561|      0|      path[n + 1 + strlen(MG_HTTP_INDEX)] =
  ------------------
  |  | 1300|      0|#define MG_HTTP_INDEX "index.html"
  ------------------
 4562|      0|          '\0';  // Remove appended .gz in index file name
 4563|   182k|    } else {
 4564|   182k|      path[n] = '\0';  // Remove appended index file name
 4565|   182k|    }
 4566|   182k|  }
 4567|   208k|  return flags;
 4568|   214k|}
fuzz.c:_ZL8uri2pathPKc6mg_strPcm:
 4499|   214k|static bool uri2path(const char *r, struct mg_str uri, char *buf, size_t len) {
 4500|   214k|  struct mg_str k, v, part, s = mg_str(r), u = {NULL, 0}, d = u;
  ------------------
  |  | 1524|   214k|#define mg_str(s) mg_str_s(s)
  ------------------
 4501|   214k|  size_t n;
 4502|   428k|  while (mg_span(s, &part, &s, ',')) {
  ------------------
  |  Branch (4502:10): [True: 214k, False: 214k]
  ------------------
 4503|   214k|    if (!mg_span(part, &k, &v, '=')) k = part, v = mg_str_n(NULL, 0);
  ------------------
  |  Branch (4503:9): [True: 0, False: 214k]
  ------------------
 4504|   214k|    if (v.len == 0) v = k, k = mg_str("/"), u = k, d = v;
  ------------------
  |  | 1524|   214k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4504:9): [True: 214k, False: 0]
  ------------------
 4505|   214k|    if (uri.len < k.len) continue;
  ------------------
  |  Branch (4505:9): [True: 0, False: 214k]
  ------------------
 4506|   214k|    if (mg_strcmp(k, mg_str_n(uri.buf, k.len)) != 0) continue;
  ------------------
  |  Branch (4506:9): [True: 23.3k, False: 191k]
  ------------------
 4507|   191k|    u = k, d = v;
 4508|   191k|  }
 4509|   214k|  n = mg_snprintf(buf, len, "%.*s", (int) d.len, d.buf);
 4510|   214k|  if (len == 0 || n + 2 >= len) return false;  // Path overflow
  ------------------
  |  Branch (4510:7): [True: 0, False: 214k]
  |  Branch (4510:19): [True: 0, False: 214k]
  ------------------
 4511|   214k|  if (n > 0 && buf[n - 1] != '/') buf[n++] = '/', buf[n] = '\0';  // Add slash
  ------------------
  |  Branch (4511:7): [True: 214k, False: 0]
  |  Branch (4511:16): [True: 214k, False: 0]
  ------------------
 4512|   214k|  if (mg_url_decode(uri.buf + u.len, uri.len - u.len, buf + n, len - n, 0) < 0) {
  ------------------
  |  Branch (4512:7): [True: 5.81k, False: 208k]
  ------------------
 4513|  5.81k|    return false;
 4514|  5.81k|  }
 4515|   208k|  buf[len - 1] = '\0';  // Double-check
 4516|   208k|  n = strlen(buf);
 4517|   208k|  if (!mg_path_is_sane(mg_str_n(buf, n))) return false;
  ------------------
  |  Branch (4517:7): [True: 273, False: 208k]
  ------------------
 4518|   479k|  while (n > 1 && buf[n - 1] == '/') buf[--n] = 0;  // Trim trailing slashes
  ------------------
  |  Branch (4518:10): [True: 294k, False: 185k]
  |  Branch (4518:19): [True: 271k, False: 22.8k]
  ------------------
 4519|   208k|  return true;
 4520|   208k|}
fuzz.c:_ZL7http_cbP13mg_connectioniPv:
 4887|   464k|static void http_cb(struct mg_connection *c, int ev, void *ev_data) {
 4888|   464k|  if (ev == MG_EV_READ || ev == MG_EV_CLOSE ||
  ------------------
  |  Branch (4888:7): [True: 5.57k, False: 458k]
  |  Branch (4888:27): [True: 5.57k, False: 452k]
  ------------------
 4889|   452k|      (ev == MG_EV_POLL && c->is_accepted && !c->is_draining &&
  ------------------
  |  Branch (4889:8): [True: 5.57k, False: 447k]
  |  Branch (4889:28): [True: 0, False: 5.57k]
  |  Branch (4889:46): [True: 0, False: 0]
  ------------------
 4890|  11.1k|       c->recv.len > 0)) {  // see #2796
  ------------------
  |  Branch (4890:8): [True: 0, False: 0]
  ------------------
 4891|  11.1k|    struct mg_http_message hm;
 4892|  11.1k|    size_t ofs = 0;  // Parsing offset
 4893|       |    // c->pfn_data is the "response generation in progress" marker. While it
 4894|       |    // is set, don't parse the next pipelined request, to keep responses in order
 4895|   225k|    while (c->pfn_data == NULL && ofs < c->recv.len) {
  ------------------
  |  Branch (4895:12): [True: 225k, False: 0]
  |  Branch (4895:35): [True: 221k, False: 3.78k]
  ------------------
 4896|   221k|      const char *buf = (char *) c->recv.buf + ofs;
 4897|   221k|      int n = mg_http_parse(buf, c->recv.len - ofs, &hm);
 4898|   221k|      struct mg_str *te;  // Transfer - encoding header
 4899|   221k|      bool is_chunked = false, is_http_1_0 = false;
 4900|   221k|      size_t old_len = c->recv.len;
 4901|   221k|      if (n < 0) {
  ------------------
  |  Branch (4901:11): [True: 2.46k, False: 219k]
  ------------------
 4902|       |        // We don't use mg_error() here, to avoid closing pipelined requests
 4903|       |        // prematurely, see #2592
 4904|  2.46k|        MG_ERROR(("HTTP parse, %lu bytes", c->recv.len));
  ------------------
  |  | 1823|  2.46k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|  2.46k|  do {                      \
  |  |  |  | 1814|  2.46k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 2.46k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  2.46k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 2.46k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4905|  2.46k|        c->is_draining = 1;
 4906|  2.46k|        mg_hexdump(buf, c->recv.len - ofs > 16 ? 16 : c->recv.len - ofs);
  ------------------
  |  Branch (4906:25): [True: 1.63k, False: 825]
  ------------------
 4907|  2.46k|        c->recv.len = 0;
 4908|  2.46k|        return;
 4909|  2.46k|      }
 4910|   219k|      if (n == 0) break;                 // Request is not buffered yet
  ------------------
  |  Branch (4910:11): [True: 3.09k, False: 216k]
  ------------------
 4911|   216k|      mg_call(c, MG_EV_HTTP_HDRS, &hm);  // Got all HTTP headers
 4912|   216k|      if (c->recv.len != old_len) {
  ------------------
  |  Branch (4912:11): [True: 0, False: 216k]
  ------------------
 4913|       |        // User manipulated received data. Wash our hands
 4914|      0|        MG_DEBUG(("%lu detaching HTTP handler", c->id));
  ------------------
  |  | 1825|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4915|      0|        c->pfn = NULL;
 4916|      0|        return;
 4917|      0|      }
 4918|   216k|      if (ev == MG_EV_CLOSE) {  // If client did not set Content-Length
  ------------------
  |  Branch (4918:11): [True: 5.37k, False: 210k]
  ------------------
 4919|  5.37k|        hm.message.len = c->recv.len - ofs;  // and closes now, deliver MSG
 4920|  5.37k|        hm.body.len = hm.message.len - (size_t) (hm.body.buf - hm.message.buf);
 4921|  5.37k|      }
 4922|   216k|      is_http_1_0 =
 4923|   216k|          hm.proto.len == 8 && mg_ncasecmp(hm.proto.buf, "HTTP/1.0", 8) == 0;
  ------------------
  |  Branch (4923:11): [True: 192k, False: 23.5k]
  |  Branch (4923:32): [True: 2.91k, False: 189k]
  ------------------
 4924|       |      // HTTP/1.0 does not use "Transfer-Encoding: chunked"
 4925|   216k|      if (!is_http_1_0 &&
  ------------------
  |  Branch (4925:11): [True: 213k, False: 2.91k]
  ------------------
 4926|   213k|          (te = mg_http_get_header(&hm, "Transfer-Encoding")) != NULL) {
  ------------------
  |  Branch (4926:11): [True: 10.6k, False: 202k]
  ------------------
 4927|  10.6k|        if (mg_strcasecmp(*te, mg_str("chunked")) == 0) {
  ------------------
  |  | 1524|  10.6k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4927:13): [True: 10.2k, False: 349]
  ------------------
 4928|  10.2k|          is_chunked = true;
 4929|  10.2k|        } else {
 4930|    349|          mg_error(c, "Invalid Transfer-Encoding");  // See #2460
 4931|    349|          return;
 4932|    349|        }
 4933|   205k|      } else if (mg_http_get_header(&hm, "Content-length") == NULL) {
  ------------------
  |  Branch (4933:18): [True: 204k, False: 1.35k]
  ------------------
 4934|       |        // #2593: HTTP packets must contain either Transfer-Encoding or
 4935|       |        // Content-length
 4936|   204k|        bool is_response = mg_ncasecmp(hm.method.buf, "HTTP/", 5) == 0;
 4937|   204k|        bool require_content_len = false;
 4938|   204k|        if (!is_response && (mg_strcasecmp(hm.method, mg_str("POST")) == 0 ||
  ------------------
  |  | 1524|   191k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4938:13): [True: 191k, False: 12.5k]
  |  Branch (4938:30): [True: 112, False: 191k]
  ------------------
 4939|   191k|                             mg_strcasecmp(hm.method, mg_str("PUT")) == 0)) {
  ------------------
  |  | 1524|   191k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4939:30): [True: 238, False: 191k]
  ------------------
 4940|       |          // POST and PUT should include an entity body. Therefore, they should
 4941|       |          // contain a Content-length header (unless the body length is 0, in
 4942|       |          // which case it can be omitted). Other requests can also contain a
 4943|       |          // body, but their content has no defined semantics (RFC 7231)
 4944|       |          // It is a non-chunked request, so the offset (ofs) is updated after
 4945|       |          // exiting this branch.
 4946|    350|          if (hm.body.len != 0) require_content_len = true;
  ------------------
  |  Branch (4946:15): [True: 6, False: 344]
  ------------------
 4947|   203k|        } else if (is_response) {
  ------------------
  |  Branch (4947:20): [True: 12.5k, False: 191k]
  ------------------
 4948|       |          // HTTP spec 7.2 Entity body: All other responses must include a body
 4949|       |          // or Content-Length header field defined with a value of 0.
 4950|  12.5k|          int status = mg_http_status(&hm);
 4951|  12.5k|          require_content_len = status >= 200 && status != 204 && status != 304;
  ------------------
  |  Branch (4951:33): [True: 11.0k, False: 1.46k]
  |  Branch (4951:50): [True: 180, False: 10.9k]
  |  Branch (4951:67): [True: 172, False: 8]
  ------------------
 4952|  12.5k|        }
 4953|   204k|        if (require_content_len) {
  ------------------
  |  Branch (4953:13): [True: 178, False: 204k]
  ------------------
 4954|    178|          if (!c->is_client) mg_http_reply(c, 411, "", "");
  ------------------
  |  Branch (4954:15): [True: 0, False: 178]
  ------------------
 4955|    178|          MG_ERROR(("Content length missing from %s",
  ------------------
  |  | 1823|    178|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|    178|  do {                      \
  |  |  |  | 1814|    178|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 178]
  |  |  |  |  |  Branch (1814:19): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|    178|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 178]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4956|    178|                    is_response ? "response" : "request"));
 4957|    178|        }
 4958|   204k|      }
 4959|       |
 4960|   215k|      if (is_chunked) {
  ------------------
  |  Branch (4960:11): [True: 10.2k, False: 205k]
  ------------------
 4961|       |        // For chunked data, strip off prefixes and suffixes from chunks
 4962|       |        // and relocate them right after the headers, then report a message
 4963|  10.2k|        char *s = (char *) c->recv.buf + ofs + n;
 4964|  10.2k|        int o = 0, pl, dl, cl, len = (int) (c->recv.len - ofs - (size_t) n);
 4965|       |
 4966|       |        // Find zero-length chunk (the end of the body)
 4967|  10.9k|        while ((cl = skip_chunk(s + o, len - o, &pl, &dl)) > 0 && dl) o += cl;
  ------------------
  |  Branch (4967:16): [True: 10.6k, False: 359]
  |  Branch (4967:67): [True: 715, False: 9.91k]
  ------------------
 4968|  10.2k|        if (cl == 0) break;  // No zero-len chunk, buffer more data
  ------------------
  |  Branch (4968:13): [True: 112, False: 10.1k]
  ------------------
 4969|  10.1k|        if (cl < 0) {
  ------------------
  |  Branch (4969:13): [True: 247, False: 9.91k]
  ------------------
 4970|    247|          mg_error(c, "Invalid chunk");
 4971|    247|          break;
 4972|    247|        }
 4973|       |
 4974|       |        // Zero chunk found. Second pass: strip + relocate
 4975|  9.91k|        o = 0, hm.body.len = 0, hm.message.len = (size_t) n;
 4976|  10.1k|        while ((cl = skip_chunk(s + o, len - o, &pl, &dl)) > 0) {
  ------------------
  |  Branch (4976:16): [True: 10.1k, False: 0]
  ------------------
 4977|  10.1k|          memmove(s + hm.body.len, s + o + pl, (size_t) dl);
 4978|  10.1k|          o += cl, hm.body.len += (size_t) dl, hm.message.len += (size_t) dl;
 4979|  10.1k|          if (dl == 0) break;
  ------------------
  |  Branch (4979:15): [True: 9.91k, False: 237]
  ------------------
 4980|  10.1k|        }
 4981|  9.91k|        ofs += (size_t) (n + o);
 4982|   205k|      } else {  // Normal, non-chunked data
 4983|   205k|        size_t len = c->recv.len - ofs - (size_t) n;
 4984|   205k|        if (hm.body.len > len) break;  // Buffer more data
  ------------------
  |  Branch (4984:13): [True: 1.09k, False: 204k]
  ------------------
 4985|   204k|        ofs += (size_t) n + hm.body.len;
 4986|   204k|      }
 4987|       |
 4988|   214k|      if (c->is_accepted) c->pfn_data = c;  // Response started
  ------------------
  |  Branch (4988:11): [True: 0, False: 214k]
  ------------------
 4989|   214k|      mg_call(c, MG_EV_HTTP_MSG, &hm);  // Handler sets pfn_data NULL when done
 4990|   214k|      if (c->is_accepted && c->pfn_data == NULL) {
  ------------------
  |  Branch (4990:11): [True: 0, False: 214k]
  |  Branch (4990:29): [True: 0, False: 0]
  ------------------
 4991|      0|        struct mg_str *cc = mg_http_get_header(&hm, "Connection");
 4992|      0|        if (cc != NULL && mg_strcasecmp(*cc, mg_str("close")) == 0) {
  ------------------
  |  | 1524|      0|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (4992:13): [True: 0, False: 0]
  |  Branch (4992:27): [True: 0, False: 0]
  ------------------
 4993|      0|          c->is_draining = 1;  // honor "Connection: close"
 4994|      0|          break;
 4995|      0|        }
 4996|      0|      }
 4997|   214k|    }
 4998|  8.34k|    if (ofs > 0) mg_iobuf_del(&c->recv, 0, ofs);  // Delete processed data
  ------------------
  |  Branch (4998:9): [True: 1.60k, False: 6.74k]
  ------------------
 4999|  8.34k|  }
 5000|   461k|  (void) ev_data;
 5001|   461k|}
fuzz.c:_ZL10skip_chunkPKciPiS1_:
 4872|  21.1k|static int skip_chunk(const char *buf, int len, int *pl, int *dl) {
 4873|  21.1k|  int i = 0, n = 0;  // pass int to mg_str_to_num, treats as unsigned
 4874|  21.1k|  if (len < 3) return 0;
  ------------------
  |  Branch (4874:7): [True: 20, False: 21.1k]
  ------------------
 4875|  12.3M|  while (i < len && is_hex_digit(buf[i])) i++;
  ------------------
  |  Branch (4875:10): [True: 12.3M, False: 24]
  |  Branch (4875:21): [True: 12.3M, False: 21.0k]
  ------------------
 4876|  21.1k|  if (i == 0) return -1;  // Error, no length specified
  ------------------
  |  Branch (4876:7): [True: 17, False: 21.1k]
  ------------------
 4877|  21.1k|  if (len < i + 2 || buf[i] != '\r' || buf[i + 1] != '\n') return -1;  // Error
  ------------------
  |  Branch (4877:7): [True: 32, False: 21.0k]
  |  Branch (4877:22): [True: 63, False: 21.0k]
  |  Branch (4877:40): [True: 7, False: 21.0k]
  ------------------
 4878|  21.0k|  if (mg_str_to_num(mg_str_n(buf, (size_t) i), 16, &n, sizeof(n)) == false)
  ------------------
  |  Branch (4878:7): [True: 34, False: 20.9k]
  ------------------
 4879|     34|    return -1;                    // Decode chunk length, overflow
 4880|  20.9k|  if (n < 0) return -1;           // Chunk length is too big <0 = >0x80000000
  ------------------
  |  Branch (4880:7): [True: 52, False: 20.9k]
  ------------------
 4881|  20.9k|  if (n > len - i - 4) return 0;  // Chunk not yet fully buffered
  ------------------
  |  Branch (4881:7): [True: 92, False: 20.8k]
  ------------------
 4882|  20.8k|  if (buf[i + n + 2] != '\r' || buf[i + n + 3] != '\n') return -1;  // Error
  ------------------
  |  Branch (4882:7): [True: 21, False: 20.8k]
  |  Branch (4882:33): [True: 21, False: 20.7k]
  ------------------
 4883|  20.7k|  *pl = i + 2, *dl = n;
 4884|  20.7k|  return i + 2 + n + 2;
 4885|  20.8k|}
fuzz.c:_ZL12is_hex_digiti:
 4867|  12.3M|static bool is_hex_digit(int c) {
 4868|  12.3M|  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
  ------------------
  |  Branch (4868:11): [True: 12.3M, False: 21.0k]
  |  Branch (4868:23): [True: 7.27M, False: 5.04M]
  |  Branch (4868:37): [True: 5.04M, False: 24.3k]
  |  Branch (4868:49): [True: 5.04M, False: 13]
  ------------------
 4869|  24.3k|         (c >= 'A' && c <= 'F');
  ------------------
  |  Branch (4869:11): [True: 3.30k, False: 21.0k]
  |  Branch (4869:23): [True: 3.27k, False: 27]
  ------------------
 4870|  12.3M|}
fuzz.c:_ZL7roundupmm:
 5023|  35.3k|static size_t roundup(size_t size, size_t align) {
 5024|  35.3k|  return align == 0 ? size : (size + align - 1) / align * align;
  ------------------
  |  Branch (5024:10): [True: 0, False: 35.3k]
  ------------------
 5025|  35.3k|}
fuzz.c:_ZL7mg_atodPKciPi:
 5120|   306k|static double mg_atod(const char *p, int len, int *numlen) {
 5121|   306k|  double d = 0.0;
 5122|   306k|  int i = 0, sign = 1;
 5123|       |
 5124|       |  // Sign
 5125|   306k|  if (i < len && *p == '-') {
  ------------------
  |  Branch (5125:7): [True: 306k, False: 0]
  |  Branch (5125:18): [True: 148k, False: 158k]
  ------------------
 5126|   148k|    sign = -1, i++;
 5127|   158k|  } else if (i < len && *p == '+') {
  ------------------
  |  Branch (5127:14): [True: 158k, False: 0]
  |  Branch (5127:25): [True: 0, False: 158k]
  ------------------
 5128|      0|    i++;
 5129|      0|  }
 5130|       |
 5131|       |  // Decimal
 5132|  7.46M|  for (; i < len && p[i] >= '0' && p[i] <= '9'; i++) {
  ------------------
  |  Branch (5132:10): [True: 7.46M, False: 130]
  |  Branch (5132:21): [True: 7.21M, False: 243k]
  |  Branch (5132:36): [True: 7.15M, False: 62.9k]
  ------------------
 5133|  7.15M|    d *= 10.0;
 5134|  7.15M|    d += p[i] - '0';
 5135|  7.15M|  }
 5136|   306k|  d *= sign;
 5137|       |
 5138|       |  // Fractional
 5139|   306k|  if (i < len && p[i] == '.') {
  ------------------
  |  Branch (5139:7): [True: 306k, False: 130]
  |  Branch (5139:18): [True: 114k, False: 192k]
  ------------------
 5140|   114k|    double frac = 0.0, base = 0.1;
 5141|   114k|    i++;
 5142|  11.7M|    for (; i < len && p[i] >= '0' && p[i] <= '9'; i++) {
  ------------------
  |  Branch (5142:12): [True: 11.7M, False: 53]
  |  Branch (5142:23): [True: 11.6M, False: 113k]
  |  Branch (5142:38): [True: 11.6M, False: 633]
  ------------------
 5143|  11.6M|      frac += base * (p[i] - '0');
 5144|  11.6M|      base /= 10.0;
 5145|  11.6M|    }
 5146|   114k|    d += frac * sign;
 5147|   114k|  }
 5148|       |
 5149|       |  // Exponential
 5150|   306k|  if (i < len && (p[i] == 'e' || p[i] == 'E')) {
  ------------------
  |  Branch (5150:7): [True: 306k, False: 183]
  |  Branch (5150:19): [True: 4.43k, False: 302k]
  |  Branch (5150:34): [True: 56.9k, False: 245k]
  ------------------
 5151|  61.3k|    int exp = 0, minus = 0;
 5152|  61.3k|    i++;
 5153|  61.3k|    if (i < len && p[i] == '-') minus = 1, i++;
  ------------------
  |  Branch (5153:9): [True: 61.3k, False: 25]
  |  Branch (5153:20): [True: 48.9k, False: 12.3k]
  ------------------
 5154|  61.3k|    if (i < len && p[i] == '+') i++;
  ------------------
  |  Branch (5154:9): [True: 61.3k, False: 36]
  |  Branch (5154:20): [True: 808, False: 60.5k]
  ------------------
 5155|  1.13M|    while (i < len && p[i] >= '0' && p[i] <= '9' && exp < 308)
  ------------------
  |  Branch (5155:12): [True: 1.13M, False: 237]
  |  Branch (5155:23): [True: 1.07M, False: 58.2k]
  |  Branch (5155:38): [True: 1.07M, False: 2.81k]
  |  Branch (5155:53): [True: 1.07M, False: 48]
  ------------------
 5156|  1.07M|      exp = exp * 10 + (p[i++] - '0');
 5157|       |    // use fast exponentiation
 5158|       |    // https://en.wikipedia.org/wiki/Exponentiation_by_squaring
 5159|  61.3k|    if (exp != 0) {
  ------------------
  |  Branch (5159:9): [True: 57.6k, False: 3.72k]
  ------------------
 5160|  57.6k|      double x = 10, y = 1;
 5161|  57.6k|      if (exp > 308) exp = 308;
  ------------------
  |  Branch (5161:11): [True: 1.16k, False: 56.5k]
  ------------------
 5162|  57.6k|      if (minus) x = 0.1;
  ------------------
  |  Branch (5162:11): [True: 48.1k, False: 9.52k]
  ------------------
 5163|   310k|      while (exp > 1) {
  ------------------
  |  Branch (5163:14): [True: 252k, False: 57.6k]
  ------------------
 5164|   252k|        if (exp & 1) {
  ------------------
  |  Branch (5164:13): [True: 78.3k, False: 174k]
  ------------------
 5165|  78.3k|          y *= x;
 5166|  78.3k|          --exp;
 5167|  78.3k|        }
 5168|   252k|        x *= x;
 5169|   252k|        exp >>= 1;
 5170|   252k|      }
 5171|  57.6k|      d *= x * y;
 5172|  57.6k|    }
 5173|  61.3k|  }
 5174|       |
 5175|   306k|  if (numlen != NULL) *numlen = i;
  ------------------
  |  Branch (5175:7): [True: 306k, False: 0]
  ------------------
 5176|   306k|  return d;
 5177|   306k|}
fuzz.c:_ZL14mg_pass_stringPKci:
 5106|  85.3k|static int mg_pass_string(const char *s, int len) {
 5107|  85.3k|  int i;
 5108|  33.5M|  for (i = 0; i < len; i++) {
  ------------------
  |  Branch (5108:15): [True: 33.5M, False: 456]
  ------------------
 5109|  33.5M|    if (s[i] == '\\' && i + 1 < len && json_esc(s[i + 1], 1)) {
  ------------------
  |  Branch (5109:9): [True: 451k, False: 33.1M]
  |  Branch (5109:25): [True: 451k, False: 58]
  |  Branch (5109:40): [True: 272k, False: 178k]
  ------------------
 5110|   272k|      i++;
 5111|  33.3M|    } else if (s[i] == '\0') {
  ------------------
  |  Branch (5111:16): [True: 70, False: 33.3M]
  ------------------
 5112|     70|      return MG_JSON_INVALID;
 5113|  33.3M|    } else if (s[i] == '"') {
  ------------------
  |  Branch (5113:16): [True: 84.8k, False: 33.2M]
  ------------------
 5114|  84.8k|      return i;
 5115|  84.8k|    }
 5116|  33.5M|  }
 5117|    456|  return MG_JSON_INVALID;
 5118|  85.3k|}
fuzz.c:_ZL8json_escii:
 5098|   451k|static char json_esc(int c, int esc) {
 5099|   451k|  const char *p, *esc1 = escapeseq(esc), *esc2 = escapeseq(!esc);
 5100|  2.89M|  for (p = esc1; *p != '\0'; p++) {
  ------------------
  |  Branch (5100:18): [True: 2.71M, False: 178k]
  ------------------
 5101|  2.71M|    if (*p == c) return esc2[p - esc1];
  ------------------
  |  Branch (5101:9): [True: 272k, False: 2.44M]
  ------------------
 5102|  2.71M|  }
 5103|   178k|  return 0;
 5104|   451k|}
fuzz.c:_ZL9escapeseqi:
 5094|   902k|static const char *escapeseq(int esc) {
 5095|   902k|  return esc ? "\b\f\n\r\t\\\"" : "bfnrt\\\"";
  ------------------
  |  Branch (5095:10): [True: 451k, False: 451k]
  ------------------
 5096|   902k|}
fuzz.c:_ZL13l2_ppp_header10mg_l2protoPh:
 6130|  3.71k|static uint8_t *l2_ppp_header(enum mg_l2proto proto, uint8_t *p) {
 6131|  3.71k|  uint16_t ppp_proto = proto == MG_TCPIP_L2PROTO_IPV4   ? MG_PPP_PROTO_IP
  ------------------
  |  | 6052|  3.71k|#define MG_PPP_PROTO_IP 0x0021
  ------------------
  |  Branch (6131:24): [True: 3.71k, False: 0]
  ------------------
 6132|  3.71k|                       : proto == MG_TCPIP_L2PROTO_IPV4 ? MG_PPP_PROTO_IPV6
  ------------------
  |  | 6053|      0|#define MG_PPP_PROTO_IPV6 0x0057
  ------------------
  |  Branch (6132:26): [True: 0, False: 0]
  ------------------
 6133|      0|                                                        : 0;
 6134|  3.71k|  return ppp_header(ppp_proto, p);
 6135|  3.71k|}
fuzz.c:_ZL10ppp_headertPh:
 6124|  4.89k|static uint8_t *ppp_header(uint16_t proto, uint8_t *p) {
 6125|  4.89k|  struct ppp *ppp = (struct ppp *) p;
 6126|  4.89k|  ppp->proto = mg_htons(proto);
  ------------------
  |  | 2094|  4.89k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6127|  4.89k|  return (uint8_t *) (ppp + 1);
 6128|  4.89k|}
fuzz.c:_ZL11hdlc_headerPh:
 6117|  3.03k|static uint8_t *hdlc_header(uint8_t *p) {
 6118|  3.03k|  struct hdlc_ *hdlc = (struct hdlc_ *) p;
 6119|  3.03k|  hdlc->addr = MG_PPP_ADDR;
  ------------------
  |  | 6049|  3.03k|#define MG_PPP_ADDR 0xff
  ------------------
 6120|  3.03k|  hdlc->ctrl = MG_PPP_CTRL;
  ------------------
  |  | 6050|  3.03k|#define MG_PPP_CTRL 0x03
  ------------------
 6121|  3.03k|  return (uint8_t *) (hdlc + 1);
 6122|  3.03k|}
fuzz.c:_ZL12pppoe_headerP11mg_tcpip_if10mg_l2protohtP9mg_l2addrS3_Ph:
 6152|  1.86k|                             struct mg_l2addr *dst, uint8_t *frame) {
 6153|  1.86k|  struct pppoe *pppoe =
 6154|  1.86k|      (struct pppoe *) mg_l2_eth_header(ifp, proto, src, dst, frame);
 6155|  1.86k|  pppoe->vertype = 0x11;
 6156|  1.86k|  pppoe->code = code;
 6157|  1.86k|  pppoe->id = id;
 6158|  1.86k|  return (uint8_t *) (pppoe + 1);
 6159|  1.86k|}
fuzz.c:_ZL13pppoe_trailerP11mg_tcpip_ifmPh:
 6184|  1.86k|static size_t pppoe_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) {
 6185|  1.86k|  struct pppoe *pppoe = (struct pppoe *) (cur - len - sizeof(struct pppoe));
 6186|  1.86k|  pppoe->len = mg_htons((uint16_t) len);
  ------------------
  |  | 2094|  1.86k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6187|  1.86k|  return mg_l2_eth_trailer(ifp, PDIFF(pppoe, cur), cur);
  ------------------
  |  | 6092|  1.86k|#define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a))))
  ------------------
 6188|  1.86k|}
fuzz.c:_ZL6ppp_rxP11mg_tcpip_ifP10mg_l2protoP6mg_strS4_:
 6402|  1.38k|                   struct mg_str *pay, struct mg_str *raw) {
 6403|  1.38k|  struct ppp *ppp = (struct ppp *) pay->buf;
 6404|  1.38k|  if (pay->len < sizeof(*ppp)) return false;  // Truncated
  ------------------
  |  Branch (6404:7): [True: 2, False: 1.38k]
  ------------------
 6405|  1.38k|  pay->buf = (char *) (ppp + 1);
 6406|  1.38k|  pay->len = pay->len - sizeof(*ppp);
 6407|  1.38k|  switch (mg_ntohs(ppp->proto)) {
 6408|     27|    case MG_PPP_PROTO_LCP:
  ------------------
  |  | 6054|     27|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
  |  Branch (6408:5): [True: 27, False: 1.35k]
  ------------------
 6409|     27|      ppp_handle_lcp(ifp, (uint8_t *) pay->buf, pay->len);
 6410|     27|      return false;
 6411|     34|    case MG_PPP_PROTO_IPCP:
  ------------------
  |  | 6055|     34|#define MG_PPP_PROTO_IPCP 0x8021
  ------------------
  |  Branch (6411:5): [True: 34, False: 1.35k]
  ------------------
 6412|     34|      if (s_lcpup) ppp_handle_ipcp(ifp, (uint8_t *) pay->buf, pay->len);
  ------------------
  |  Branch (6412:11): [True: 33, False: 1]
  ------------------
 6413|     34|      return false;
 6414|     24|    case MG_PPP_PROTO_IP:
  ------------------
  |  | 6052|     24|#define MG_PPP_PROTO_IP 0x0021
  ------------------
  |  Branch (6414:5): [True: 24, False: 1.36k]
  ------------------
 6415|     24|      if (!s_lcpup) return false;
  ------------------
  |  Branch (6415:11): [True: 0, False: 24]
  ------------------
 6416|     24|      MG_VERBOSE(("got IP packet of %d bytes", pay->len));
  ------------------
  |  | 1826|     24|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1813|     24|  do {                      \
  |  |  |  | 1814|     24|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 24]
  |  |  |  |  ------------------
  |  |  |  | 1815|     24|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 24]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6417|     24|      *proto = MG_TCPIP_L2PROTO_IPV4;
 6418|     24|      break;
 6419|       |#if MG_ENABLE_IPV6
 6420|       |    case MG_PPP_PROTO_IPV6CP:
 6421|       |      if (s_lcpup) ppp_handle_ipv6cp(ifp, (uint8_t *) pay->buf, pay->len);
 6422|       |      return false;
 6423|       |    case MG_PPP_PROTO_IPV6:
 6424|       |      if (!s_lcpup) return false;
 6425|       |      MG_VERBOSE(("got IPv6 packet of %d bytes", pay->len));
 6426|       |      *proto = MG_TCPIP_L2PROTO_IPV6;
 6427|       |      break;
 6428|       |#endif
 6429|  1.29k|    default: {
  ------------------
  |  Branch (6429:5): [True: 1.29k, False: 85]
  ------------------
 6430|  1.29k|      struct lcp rej;
 6431|  1.29k|      uint8_t *p;
 6432|  1.29k|      size_t msglen;
 6433|  1.29k|      MG_DEBUG(("unknown %u-byte PPP frame with proto 0x%04x:",
  ------------------
  |  | 1825|  1.29k|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|  1.29k|  do {                      \
  |  |  |  | 1814|  1.29k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 1.29k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  1.29k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 1.29k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6434|  1.29k|                pay->len + sizeof(*ppp), mg_ntohs(ppp->proto)));
 6435|  1.29k|      if (mg_log_level >= MG_LL_DEBUG)
  ------------------
  |  Branch (6435:11): [True: 0, False: 1.29k]
  ------------------
 6436|      0|        mg_hexdump(ppp, pay->len > 14 ? 16 : pay->len + sizeof(*ppp));
  ------------------
  |  Branch (6436:25): [True: 0, False: 0]
  ------------------
 6437|  1.29k|      if (!s_lcpup) return false;  // RFC-1661 5.7: must reject on link down
  ------------------
  |  Branch (6437:11): [True: 149, False: 1.15k]
  ------------------
 6438|  1.15k|      if (pay->len > (size_t) (ifp->mtu - 20))
  ------------------
  |  Branch (6438:11): [True: 3, False: 1.14k]
  ------------------
 6439|      3|        pay->len = (size_t) (ifp->mtu - 20);  // truncate to some safe limit
 6440|  1.15k|      rej.code = MG_PPP_LCP_REJECT;
  ------------------
  |  | 6066|  1.15k|#define MG_PPP_LCP_REJECT 8
  ------------------
 6441|  1.15k|      mg_random(&rej.id, sizeof(rej.id));
 6442|  1.15k|      msglen = pay->len + sizeof(*ppp);
 6443|  1.15k|      rej.len = mg_htons((uint16_t) (msglen + sizeof(rej)));
  ------------------
  |  | 2094|  1.15k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 6444|  1.15k|      p = ppp_tx_frame_header(ifp, MG_PPP_PROTO_LCP);
  ------------------
  |  | 6054|  1.15k|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
 6445|  1.15k|      memmove(p, &rej, sizeof(rej));          // LCP reject
 6446|  1.15k|      memmove(p + sizeof(rej), ppp, msglen);  // rejected PPP message
 6447|  1.15k|      ppp_tx_frame_trailer(ifp, msglen + sizeof(rej), p + msglen + sizeof(rej));
 6448|  1.15k|    }
 6449|      0|      return false;
 6450|  1.38k|  }
 6451|     24|  (void) raw;
 6452|     24|  return true;
 6453|  1.38k|}
fuzz.c:_ZL14ppp_handle_lcpP11mg_tcpip_ifPhm:
 6220|     27|                           size_t lcpsz) {
 6221|     27|  uint8_t id;
 6222|     27|  uint16_t len;
 6223|     27|  struct lcp *lcp = (struct lcp *) lcpp;
 6224|     27|  if (lcpsz < sizeof(*lcp)) return;
  ------------------
  |  Branch (6224:7): [True: 1, False: 26]
  ------------------
 6225|     26|  id = lcp->id;
 6226|     26|  len = mg_ntohs(lcp->len);
 6227|     26|  if (len < sizeof(*lcp) || len > lcpsz) return;
  ------------------
  |  Branch (6227:7): [True: 0, False: 26]
  |  Branch (6227:29): [True: 17, False: 9]
  ------------------
 6228|      9|  switch (lcp->code) {
  ------------------
  |  Branch (6228:11): [True: 5, False: 4]
  ------------------
 6229|      2|    case MG_PPP_LCP_CFG_REQ: {
  ------------------
  |  | 6060|      2|#define MG_PPP_LCP_CFG_REQ 1
  ------------------
  |  Branch (6229:5): [True: 2, False: 7]
  ------------------
 6230|      2|      if (len == sizeof(*lcp)) {
  ------------------
  |  Branch (6230:11): [True: 2, False: 0]
  ------------------
 6231|      2|        MG_DEBUG(("LCP config request of %d bytes, acknowledging...", len));
  ------------------
  |  | 1825|      2|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      2|  do {                      \
  |  |  |  | 1814|      2|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  |  | 1815|      2|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6232|      2|        lcp->code = MG_PPP_LCP_CFG_ACK;
  ------------------
  |  | 6061|      2|#define MG_PPP_LCP_CFG_ACK 2
  ------------------
 6233|      2|        ppp_tx_frame(ifp, MG_PPP_PROTO_LCP, lcpp, len);
  ------------------
  |  | 6054|      2|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
 6234|      2|        lcp->code = MG_PPP_LCP_CFG_REQ;
  ------------------
  |  | 6060|      2|#define MG_PPP_LCP_CFG_REQ 1
  ------------------
 6235|      2|        ppp_tx_frame(ifp, MG_PPP_PROTO_LCP, lcpp, len);
  ------------------
  |  | 6054|      2|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
 6236|      2|      } else {
 6237|      0|        MG_DEBUG(("LCP config request of %d bytes, rejecting...", len));
  ------------------
  |  | 1825|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6238|      0|        lcp->code = MG_PPP_LCP_CFG_REJECT;
  ------------------
  |  | 6063|      0|#define MG_PPP_LCP_CFG_REJECT 4
  ------------------
 6239|      0|        ppp_tx_frame(ifp, MG_PPP_PROTO_LCP, lcpp, len);
  ------------------
  |  | 6054|      0|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
 6240|      0|      }
 6241|      2|    } break;
 6242|      0|    case MG_PPP_LCP_CFG_ACK:
  ------------------
  |  | 6061|      0|#define MG_PPP_LCP_CFG_ACK 2
  ------------------
  |  Branch (6242:5): [True: 0, False: 9]
  ------------------
 6243|      0|      s_lcpup = true;
 6244|      0|      break;
 6245|      2|    case MG_PPP_LCP_CFG_TERM_REQ: {
  ------------------
  |  | 6064|      2|#define MG_PPP_LCP_CFG_TERM_REQ 5
  ------------------
  |  Branch (6245:5): [True: 2, False: 7]
  ------------------
 6246|      2|      uint8_t ack[4] = {MG_PPP_LCP_CFG_TERM_ACK, id, 0, 4};
  ------------------
  |  | 6065|      2|#define MG_PPP_LCP_CFG_TERM_ACK 6
  ------------------
 6247|      2|      MG_DEBUG(("LCP termination request, acknowledging..."));
  ------------------
  |  | 1825|      2|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      2|  do {                      \
  |  |  |  | 1814|      2|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  |  | 1815|      2|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6248|      2|      ppp_tx_frame(ifp, MG_PPP_PROTO_LCP, ack, sizeof(ack));
  ------------------
  |  | 6054|      2|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
 6249|      2|      s_lcpup = false;
 6250|      2|    } break;
 6251|      1|    case MG_PPP_LCP_ECHO_REQ:  // RFC-1661 5.8: must respond
  ------------------
  |  | 6067|      1|#define MG_PPP_LCP_ECHO_REQ 9
  ------------------
  |  Branch (6251:5): [True: 1, False: 8]
  ------------------
 6252|      1|      MG_DEBUG(("LCP echo request of %d bytes, replying...", len));
  ------------------
  |  | 1825|      1|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      1|  do {                      \
  |  |  |  | 1814|      1|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  |  | 1815|      1|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6253|      1|      lcp->code = MG_PPP_LCP_ECHO_REPLY;
  ------------------
  |  | 6068|      1|#define MG_PPP_LCP_ECHO_REPLY 10
  ------------------
 6254|      1|      ppp_tx_frame(ifp, MG_PPP_PROTO_LCP, lcpp, len);
  ------------------
  |  | 6054|      1|#define MG_PPP_PROTO_LCP 0xc021
  ------------------
 6255|      1|      break;
 6256|      9|  }
 6257|      9|}
fuzz.c:_ZL12ppp_tx_frameP11mg_tcpip_iftPhm:
 6213|     25|                           uint8_t *data, size_t datasz) {
 6214|     25|  uint8_t *pay = ppp_tx_frame_header(ifp, proto);
 6215|     25|  memcpy(pay, data, datasz);
 6216|     25|  return ppp_tx_frame_trailer(ifp, datasz, pay + datasz);
 6217|     25|}
fuzz.c:_ZL15ppp_handle_ipcpP11mg_tcpip_ifPhm:
 6275|     33|                            size_t ipcpsz) {
 6276|     33|  uint16_t len;
 6277|     33|  uint8_t id;
 6278|     33|  struct ipcp *ipcp = (struct ipcp *) ipcpp;
 6279|     33|  uint8_t req[] = {
 6280|     33|      MG_PPP_IPCP_CFG_REQ, 0, 0, 10, MG_PPP_IPCP_OPT_IPADDR, 6, 0, 0, 0, 0};
  ------------------
  |  | 6070|     33|#define MG_PPP_IPCP_CFG_REQ 1
  ------------------
                    MG_PPP_IPCP_CFG_REQ, 0, 0, 10, MG_PPP_IPCP_OPT_IPADDR, 6, 0, 0, 0, 0};
  ------------------
  |  | 6074|     33|#define MG_PPP_IPCP_OPT_IPADDR 3
  ------------------
 6281|     33|  if (ipcpsz < sizeof(*ipcp)) return;
  ------------------
  |  Branch (6281:7): [True: 2, False: 31]
  ------------------
 6282|     31|  id = ipcp->id;
 6283|     31|  len = mg_ntohs(ipcp->len);
 6284|     31|  if (len < sizeof(*ipcp) || len > ipcpsz) return;
  ------------------
  |  Branch (6284:7): [True: 3, False: 28]
  |  Branch (6284:30): [True: 11, False: 17]
  ------------------
 6285|     17|  switch (ipcp->code) {
  ------------------
  |  Branch (6285:11): [True: 17, False: 0]
  ------------------
 6286|      8|    case MG_PPP_IPCP_CFG_REQ:
  ------------------
  |  | 6070|      8|#define MG_PPP_IPCP_CFG_REQ 1
  ------------------
  |  Branch (6286:5): [True: 8, False: 9]
  ------------------
 6287|      8|      MG_VERBOSE(("got IPCP config request, acknowledging..."));
  ------------------
  |  | 1826|      8|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1813|      8|  do {                      \
  |  |  |  | 1814|      8|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 8]
  |  |  |  |  ------------------
  |  |  |  | 1815|      8|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 8]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6288|      8|      if (len >= 10 &&
  ------------------
  |  Branch (6288:11): [True: 8, False: 0]
  ------------------
 6289|      8|          find_opt(MG_PPP_IPCP_OPT_IPADDR, 6, (const uint8_t *) (ipcp + 1),
  ------------------
  |  | 6074|      8|#define MG_PPP_IPCP_OPT_IPADDR 3
  ------------------
  |  Branch (6289:11): [True: 2, False: 6]
  ------------------
 6290|      8|                   len - sizeof(*ipcp), (uint8_t *) &ifp->gw)) {
 6291|      2|        MG_DEBUG(("IPCP cfg, GW IP: %M", mg_print_ip4, &ifp->gw));
  ------------------
  |  | 1825|      2|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      2|  do {                      \
  |  |  |  | 1814|      2|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  |  | 1815|      2|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6292|      2|        ipcp->code = MG_PPP_IPCP_CFG_ACK;
  ------------------
  |  | 6071|      2|#define MG_PPP_IPCP_CFG_ACK 2
  ------------------
 6293|      6|      } else if (ifp->gw == 0) {
  ------------------
  |  Branch (6293:18): [True: 0, False: 6]
  ------------------
 6294|      0|        MG_ERROR(("Peer did not provide its IP address"));
  ------------------
  |  | 1823|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6295|       |        // NOTE: We should NACK with an added option, probably we can just store
 6296|       |        // the incoming address and offer a statically configured ifp->gw when
 6297|       |        // theirs == 0, but it is unlikely to find such a dumb PPP server and it
 6298|       |        // will complicate our config and this protocol state machine
 6299|      0|        ipcp->code = MG_PPP_IPCP_CFG_REJECT;
  ------------------
  |  | 6073|      0|#define MG_PPP_IPCP_CFG_REJECT 4
  ------------------
 6300|      0|        ppp_tx_frame(ifp, MG_PPP_PROTO_IPCP, ipcpp, len);
  ------------------
  |  | 6055|      0|#define MG_PPP_PROTO_IPCP 0x8021
  ------------------
 6301|      0|      }
 6302|      8|      ppp_tx_frame(ifp, MG_PPP_PROTO_IPCP, ipcpp, len);
  ------------------
  |  | 6055|      8|#define MG_PPP_PROTO_IPCP 0x8021
  ------------------
 6303|      8|      req[1] = id;
 6304|      8|      memcpy(req + 6, &ifp->ip, 4);  // Request config IP address or 0.0.0.0
 6305|      8|      ppp_tx_frame(ifp, MG_PPP_PROTO_IPCP, req, sizeof(req));
  ------------------
  |  | 6055|      8|#define MG_PPP_PROTO_IPCP 0x8021
  ------------------
 6306|      8|      break;
 6307|      0|    case MG_PPP_IPCP_CFG_ACK:
  ------------------
  |  | 6071|      0|#define MG_PPP_IPCP_CFG_ACK 2
  ------------------
  |  Branch (6307:5): [True: 0, False: 17]
  ------------------
 6308|       |      // Our peer accepted our IP address
 6309|      0|      MG_VERBOSE(("got IPCP config ack"));
  ------------------
  |  | 1826|      0|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6310|      0|      ifp->mask = 0xffffffff;  // send to gw
 6311|      0|      ifp->state = MG_TCPIP_STATE_IP;
  ------------------
  |  | 4739|      0|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
 6312|      0|      ifp->gw_ready = true;
 6313|      0|      break;
 6314|      8|    case MG_PPP_IPCP_CFG_NACK:
  ------------------
  |  | 6072|      8|#define MG_PPP_IPCP_CFG_NACK 3
  ------------------
  |  Branch (6314:5): [True: 8, False: 9]
  ------------------
 6315|      8|      MG_VERBOSE(("got IPCP config nack"));
  ------------------
  |  | 1826|      8|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1813|      8|  do {                      \
  |  |  |  | 1814|      8|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 8]
  |  |  |  |  ------------------
  |  |  |  | 1815|      8|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 8]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6316|       |      // NACK contains our "suggested" IP address, use it
 6317|      8|      if (len >= 10 &&
  ------------------
  |  Branch (6317:11): [True: 7, False: 1]
  ------------------
 6318|      7|          find_opt(MG_PPP_IPCP_OPT_IPADDR, 6, (const uint8_t *) (ipcp + 1),
  ------------------
  |  | 6074|      7|#define MG_PPP_IPCP_OPT_IPADDR 3
  ------------------
  |  Branch (6318:11): [True: 2, False: 5]
  ------------------
 6319|      7|                   len - sizeof(*ipcp), (uint8_t *) &ifp->ip)) {
 6320|      2|        MG_DEBUG(("IPCP cfg, IP: %M", mg_print_ip4, &ifp->ip));
  ------------------
  |  | 1825|      2|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      2|  do {                      \
  |  |  |  | 1814|      2|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  |  | 1815|      2|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 2]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6321|      2|        ipcp->code = MG_PPP_IPCP_CFG_REQ;
  ------------------
  |  | 6070|      2|#define MG_PPP_IPCP_CFG_REQ 1
  ------------------
 6322|      2|        ppp_tx_frame(ifp, MG_PPP_PROTO_IPCP, ipcpp, len);
  ------------------
  |  | 6055|      2|#define MG_PPP_PROTO_IPCP 0x8021
  ------------------
 6323|      2|      }
 6324|      8|      break;
 6325|      1|    case MG_PPP_IPCP_CFG_REJECT:
  ------------------
  |  | 6073|      1|#define MG_PPP_IPCP_CFG_REJECT 4
  ------------------
  |  Branch (6325:5): [True: 1, False: 16]
  ------------------
 6326|      1|      MG_ERROR(("Peer rejected our IP address, need to properly set ifp->ip"));
  ------------------
  |  | 1823|      1|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|      1|  do {                      \
  |  |  |  | 1814|      1|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  |  | 1815|      1|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 1]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 6327|      1|      break;
 6328|     17|  }
 6329|     17|}
fuzz.c:_ZL8find_opthhPKhmPh:
 6260|     15|                     const uint8_t *opts, size_t optslen, uint8_t *dest) {
 6261|     15|  uint8_t *p = (uint8_t *) opts;
 6262|     60|  while (optslen >= 2) {  // parse options for requested one
  ------------------
  |  Branch (6262:10): [True: 58, False: 2]
  ------------------
 6263|     58|    if (p[1] > optslen || p[1] < 2) return false;  // truncated / malformed
  ------------------
  |  Branch (6263:9): [True: 9, False: 49]
  |  Branch (6263:27): [True: 0, False: 49]
  ------------------
 6264|     49|    if (p[0] == opt && p[1] == optlen) {
  ------------------
  |  Branch (6264:9): [True: 20, False: 29]
  |  Branch (6264:24): [True: 4, False: 16]
  ------------------
 6265|      4|      memcpy(dest, p + 2, optlen - 2);
 6266|      4|      return true;
 6267|      4|    }
 6268|     45|    optslen -= p[1];
 6269|     45|    p += p[1];
 6270|     45|  }
 6271|      2|  return false;
 6272|     15|}
fuzz.c:_ZL19ppp_tx_frame_headerP11mg_tcpip_ift:
 6196|  1.17k|static uint8_t *ppp_tx_frame_header(struct mg_tcpip_if *ifp, uint16_t proto) {
 6197|  1.17k|  uint8_t *l2p = (uint8_t *) ifp->tx.buf;
 6198|  1.17k|  if (ifp->l2type == MG_TCPIP_L2_PPP)
  ------------------
  |  Branch (6198:7): [True: 1.17k, False: 4]
  ------------------
 6199|  1.17k|    return ppp_header(proto, hdlc_header(l2p));
 6200|      4|  return ppp_header(proto, pppoe_header(ifp, MG_TCPIP_L2PROTO_PPPoE_SESS, 0,
 6201|      4|                                        s_id, (struct mg_l2addr *) ifp->mac,
 6202|      4|                                        (struct mg_l2addr *) ifp->gwmac, l2p));
 6203|  1.17k|}
fuzz.c:_ZL20ppp_tx_frame_trailerP11mg_tcpip_ifmPh:
 6205|  1.17k|                                   uint8_t *cur) {
 6206|  1.17k|  return mg_l2_driver_output(ifp, ifp->l2type == MG_TCPIP_L2_PPPoE
  ------------------
  |  Branch (6206:35): [True: 4, False: 1.17k]
  ------------------
 6207|  1.17k|                                      ? mg_l2_pppoe_trailer(ifp, len, cur)
 6208|  1.17k|                                      : mg_l2_ppp_trailer(ifp, len, cur));
 6209|  1.17k|}
fuzz.c:_ZL4logsPKcm:
 6922|  15.7k|static void logs(const char *buf, size_t len) {
 6923|  15.7k|  size_t i;
 6924|  90.0k|  for (i = 0; i < len; i++) logc(((unsigned char *) buf)[i]);
  ------------------
  |  Branch (6924:15): [True: 74.2k, False: 15.7k]
  ------------------
 6925|  15.7k|}
fuzz.c:_ZL4logch:
 6918|   184k|static void logc(unsigned char c) {
 6919|   184k|  s_log_func((char) c, s_log_func_param);
 6920|   184k|}
fuzz.c:_ZL6nibblej:
 6951|  74.4k|static unsigned char nibble(unsigned c) {
 6952|  74.4k|  return (unsigned char) (c < 10 ? c + '0' : c + 'W');
  ------------------
  |  Branch (6952:27): [True: 58.8k, False: 15.6k]
  ------------------
 6953|  74.4k|}
fuzz.c:_ZL20mqtt_prop_type_by_idh:
 7719|  5.60k|static int mqtt_prop_type_by_id(uint8_t prop_id) {
 7720|  5.60k|  size_t i, num_properties = sizeof(s_prop_map) / sizeof(s_prop_map[0]);
 7721|   109k|  for (i = 0; i < num_properties; ++i) {
  ------------------
  |  Branch (7721:15): [True: 109k, False: 102]
  ------------------
 7722|   109k|    if (s_prop_map[i].id == prop_id) return s_prop_map[i].type;
  ------------------
  |  Branch (7722:9): [True: 5.50k, False: 103k]
  ------------------
 7723|   109k|  }
 7724|    102|  return -1;  // Property ID not found
 7725|  5.60k|}
fuzz.c:_ZL13decode_varintPKhmPj:
 7707|  1.04k|static size_t decode_varint(const uint8_t *buf, size_t len, uint32_t *value) {
 7708|  1.04k|  uint32_t mul = 1, ofs;
 7709|  1.04k|  *value = 0;
 7710|  1.27k|  for (ofs = 0; ofs < 4 && ofs < len; ofs++) {
  ------------------
  |  Branch (7710:17): [True: 1.25k, False: 15]
  |  Branch (7710:28): [True: 1.24k, False: 14]
  ------------------
 7711|  1.24k|    uint8_t enc_byte = buf[ofs];
 7712|  1.24k|    *value += (enc_byte & 0x7f) * mul;
 7713|  1.24k|    mul *= 128;
 7714|  1.24k|    if ((enc_byte & 0x80) == 0) return ofs + 1;
  ------------------
  |  Branch (7714:9): [True: 1.02k, False: 224]
  ------------------
 7715|  1.24k|  }
 7716|     29|  return 0;
 7717|  1.04k|}
fuzz.c:_ZL8mg_atone6mg_strP7mg_addr:
 8293|  5.57k|static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
 8294|  5.57k|  if (str.len > 0) return false;
  ------------------
  |  Branch (8294:7): [True: 5.57k, False: 0]
  ------------------
 8295|      0|  memset(addr->addr.ip, 0, sizeof(addr->addr.ip));
 8296|      0|  addr->is_ip6 = false;
 8297|      0|  return true;
 8298|  5.57k|}
fuzz.c:_ZL8mg_atonl6mg_strP7mg_addr:
 8285|  5.57k|static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
 8286|  5.57k|  uint32_t localhost = mg_htonl(0x7f000001);
  ------------------
  |  | 2095|  5.57k|#define mg_htonl(x) mg_ntohl(x)
  ------------------
 8287|  5.57k|  if (mg_strcasecmp(str, mg_str("localhost")) != 0) return false;
  ------------------
  |  | 1524|  5.57k|#define mg_str(s) mg_str_s(s)
  ------------------
  |  Branch (8287:7): [True: 0, False: 5.57k]
  ------------------
 8288|  5.57k|  memcpy(addr->addr.ip, &localhost, sizeof(uint32_t));
 8289|  5.57k|  addr->is_ip6 = false;
 8290|  5.57k|  return true;
 8291|  5.57k|}
fuzz.c:_ZL13driver_outputP11mg_tcpip_ifm:
 8989|  5.57k|static size_t driver_output(struct mg_tcpip_if *ifp, size_t len) {
 8990|  5.57k|  size_t n = ifp->driver->tx(ifp->tx.buf, len, ifp);
 8991|  5.57k|  if (n == len) ifp->nsent++;
  ------------------
  |  Branch (8991:7): [True: 5.57k, False: 0]
  ------------------
 8992|  5.57k|  return n;
 8993|  5.57k|}
fuzz.c:_ZL5tx_ipP11mg_tcpip_ifPhhhjjm:
 9040|  5.57k|                        size_t plen) {
 9041|       |  // ifp->tx.buf is 8-bit aligned, keep other headers as pointers, see pkt
 9042|  5.57k|  uint8_t *l2p = (uint8_t *) ifp->tx.buf;
 9043|  5.57k|  struct ip *ip = (struct ip *) mg_l2_header(ifp, MG_TCPIP_L2PROTO_IPV4,
 9044|  5.57k|                                             ifp->mac, l2_dst, l2p);
 9045|  5.57k|  memset(ip, 0, sizeof(*ip));
 9046|  5.57k|  ip->ver = 0x45;  // Version 4, header length 5 words
 9047|  5.57k|  ip->tos = (uint8_t) (dscp << 2);
 9048|  5.57k|  ip->frag = mg_htons(0x4000);  // Don't fragment
  ------------------
  |  | 2094|  5.57k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 9049|  5.57k|  ip->len = mg_htons((uint16_t) (sizeof(*ip) + plen));
  ------------------
  |  | 2094|  5.57k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 9050|  5.57k|  ip->ttl = 64;
 9051|  5.57k|  ip->proto = proto;
 9052|  5.57k|  ip->src = ip_src;
 9053|  5.57k|  ip->dst = ip_dst;
 9054|  5.57k|  ip->csum = ipcsum(ip, sizeof(*ip));
 9055|  5.57k|  return ip;
 9056|  5.57k|}
fuzz.c:_ZL6ipcsumPKvm:
 8878|  5.60k|static uint16_t ipcsum(const void *buf, size_t len) {
 8879|  5.60k|  uint32_t sum = csumup(0, buf, len);
 8880|  5.60k|  return csumfin(sum);
 8881|  5.60k|}
fuzz.c:_ZL6csumupjPKvm:
 8866|  16.7k|static uint32_t csumup(uint32_t sum, const void *buf, size_t len) {
 8867|  16.7k|  size_t i;
 8868|  16.7k|  const uint8_t *p = (const uint8_t *) buf;
 8869|   329k|  for (i = 0; i < len; i++) sum += i & 1 ? p[i] : ((uint32_t) p[i]) << 8;
  ------------------
  |  Branch (8869:15): [True: 312k, False: 16.7k]
  |  Branch (8869:36): [True: 156k, False: 156k]
  ------------------
 8870|  16.7k|  return sum;
 8871|  16.7k|}
fuzz.c:_ZL7csumfinj:
 8873|  11.1k|static uint16_t csumfin(uint32_t sum) {
 8874|  22.3k|  while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
  ------------------
  |  Branch (8874:10): [True: 11.1k, False: 11.1k]
  ------------------
 8875|  11.1k|  return mg_htons((uint16_t) ((uint16_t) ~sum & 0xffff));
  ------------------
  |  | 2094|  11.1k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 8876|  11.1k|}
fuzz.c:_ZL5pcsumPvS_m:
 8892|  5.57k|static uint16_t pcsum(void *d, void *p, size_t plen) {
 8893|  5.57k|  uint32_t sum;
 8894|  5.57k|  struct ip *ip = (struct ip *) d;
 8895|       |#if defined(__DCC__)
 8896|       |  volatile /* Makes PPC & Diab4.3 happy */
 8897|       |#endif
 8898|  5.57k|      struct pseudoip pip;
 8899|  5.57k|  pip.src = ip->src;
 8900|  5.57k|  pip.dst = ip->dst;
 8901|  5.57k|  pip.zero = 0;
 8902|  5.57k|  pip.proto = ip->proto;
 8903|  5.57k|  pip.len = mg_htons((uint16_t) plen);
  ------------------
  |  | 2094|  5.57k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 8904|  5.57k|  sum = csumup(0, &pip, sizeof(pip));  // even length
 8905|  5.57k|  sum = csumup(sum, p, plen);          // possibly odd length: last
 8906|  5.57k|  return csumfin(sum);
 8907|  5.57k|}
fuzz.c:_ZL6tx_tcpP11mg_tcpip_ifPhP7mg_addrS3_hhjjtPKvm:
 9853|  5.57k|                     uint16_t win, const void *buf, size_t len) {
 9854|  5.57k|  uint8_t *l3p;
 9855|  5.57k|  struct ip *ip = NULL;
 9856|  5.57k|  struct tcp *tcp;
 9857|  5.57k|  uint16_t opts[4 / 2];
 9858|  5.57k|  size_t hlen = sizeof(*tcp);
 9859|       |#if MG_ENABLE_IPV6
 9860|       |  struct ip6 *ip6 = NULL;
 9861|       |#endif
 9862|       |
 9863|       |  // Handle any options first, here, to determine header size
 9864|  5.57k|  if (flags & TH_SYN) {  // Send MSS
  ------------------
  |  | 8745|  5.57k|#define TH_SYN 0x02
  ------------------
  |  Branch (9864:7): [True: 5.57k, False: 0]
  ------------------
 9865|  5.57k|    uint16_t mss;
 9866|       |#if MG_ENABLE_IPV6  // RFC-9293 3.7.1; RFC-6691 2
 9867|       |    mss = (uint16_t) (ifp->mtu - 60);
 9868|       |#else
 9869|  5.57k|    mss = (uint16_t) (ifp->mtu - 40);
 9870|  5.57k|#endif
 9871|  5.57k|    opts[0] = mg_htons(0x0204);  // RFC-9293 3.2
  ------------------
  |  | 2094|  5.57k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 9872|  5.57k|    opts[1] = mg_htons(mss);
  ------------------
  |  | 2094|  5.57k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 9873|  5.57k|    hlen += sizeof(opts);  // always whole number of 32-bit words
 9874|  5.57k|  }
 9875|       |
 9876|       |#if MG_ENABLE_IPV6
 9877|       |  if (ip_dst->is_ip6) {
 9878|       |    ip6 = tx_ip6(ifp, l2_dst, 6, dscp, ip_src->addr.ip6, ip_dst->addr.ip6,
 9879|       |                 hlen + len);
 9880|       |    tcp = (struct tcp *) (ip6 + 1);
 9881|       |    l3p = (uint8_t *) ip6;
 9882|       |  } else
 9883|       |#endif
 9884|  5.57k|  {
 9885|  5.57k|    ip = tx_ip(ifp, l2_dst, 6, dscp, ip_src->addr.ip4, ip_dst->addr.ip4,
 9886|  5.57k|               hlen + len);
 9887|  5.57k|    tcp = (struct tcp *) (ip + 1);
 9888|  5.57k|    l3p = (uint8_t *) ip;
 9889|  5.57k|  }
 9890|  5.57k|  memset(tcp, 0, sizeof(*tcp));
 9891|  5.57k|  memmove(tcp + 1, opts, hlen - sizeof(*tcp));  // copy opts if any
 9892|  5.57k|  if (buf != NULL && len) memmove((uint8_t *) tcp + hlen, buf, len);
  ------------------
  |  Branch (9892:7): [True: 0, False: 5.57k]
  |  Branch (9892:22): [True: 0, False: 0]
  ------------------
 9893|  5.57k|  tcp->sport = ip_src->port;
 9894|  5.57k|  tcp->dport = ip_dst->port;
 9895|  5.57k|  tcp->seq = seq;
 9896|  5.57k|  tcp->ack = ack;
 9897|  5.57k|  tcp->flags = flags;
 9898|  5.57k|  tcp->win = mg_htons(win);
  ------------------
  |  | 2094|  5.57k|#define mg_htons(x) mg_ntohs(x)
  ------------------
 9899|  5.57k|  tcp->off = (uint8_t) (hlen / 4 << 4);
 9900|       |#if MG_ENABLE_IPV6
 9901|       |  if (ip_dst->is_ip6) {
 9902|       |    tcp->csum = p6csum(ip6, tcp, 6, hlen + len);
 9903|       |  } else
 9904|       |#endif
 9905|  5.57k|  {
 9906|  5.57k|    tcp->csum = pcsum(ip, tcp, hlen + len);
 9907|  5.57k|  }
 9908|  5.57k|  MG_VERBOSE(("TCP %M -> %M fl %x len %u", mg_print_ip_port, ip_src,
  ------------------
  |  | 1826|  5.57k|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1813|  5.57k|  do {                      \
  |  |  |  | 1814|  5.57k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  5.57k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 5.57k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 9909|  5.57k|              mg_print_ip_port, ip_dst, tcp->flags, len));
 9910|  5.57k|  return driver_output(
 9911|  5.57k|      ifp, mg_l2_trailer(ifp, PDIFF(l3p, (uint8_t *) tcp + hlen + len),
  ------------------
  |  | 8613|  5.57k|#define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a))))
  ------------------
 9912|  5.57k|                         (uint8_t *) tcp + hlen + len));
 9913|  5.57k|}
fuzz.c:_ZL8settmoutP13mg_connectionh:
 8975|  10.5k|static void settmout(struct mg_connection *c, uint8_t type) {
 8976|  10.5k|  struct mg_tcpip_if *ifp = c->mgr->ifp;
 8977|  10.5k|  struct connstate *s = (struct connstate *) (c + 1);
 8978|  10.5k|  unsigned n = type == MIP_TTYPE_ACK   ? MG_TCPIP_ACK_MS
  ------------------
  |  | 8654|  10.5k|#define MIP_TTYPE_ACK 1        // Peer sent us data, we have to ack it soon
  ------------------
                unsigned n = type == MIP_TTYPE_ACK   ? MG_TCPIP_ACK_MS
  ------------------
  |  | 8619|      0|#define MG_TCPIP_ACK_MS 150    // Timeout for ACKing
  ------------------
  |  Branch (8978:16): [True: 0, False: 10.5k]
  ------------------
 8979|  10.5k|               : type == MIP_TTYPE_ARP ? MG_TCPIP_ARP_MS
  ------------------
  |  | 8655|  10.5k|#define MIP_TTYPE_ARP 2        // ARP resolve sent, waiting for response
  ------------------
                             : type == MIP_TTYPE_ARP ? MG_TCPIP_ARP_MS
  ------------------
  |  | 8620|      0|#define MG_TCPIP_ARP_MS 100    // Timeout for ARP response
  ------------------
  |  Branch (8979:18): [True: 0, False: 10.5k]
  ------------------
 8980|  10.5k|               : type == MIP_TTYPE_SYN ? MG_TCPIP_SYN_MS
  ------------------
  |  | 8656|  10.5k|#define MIP_TTYPE_SYN 3        // SYN sent, waiting for response
  ------------------
                             : type == MIP_TTYPE_SYN ? MG_TCPIP_SYN_MS
  ------------------
  |  | 8621|  5.57k|#define MG_TCPIP_SYN_MS 15000  // Timeout for connection establishment
  ------------------
  |  Branch (8980:18): [True: 5.57k, False: 4.99k]
  ------------------
 8981|  10.5k|               : type == MIP_TTYPE_FIN ? MG_TCPIP_FIN_MS
  ------------------
  |  | 8657|  4.99k|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
                             : type == MIP_TTYPE_FIN ? MG_TCPIP_FIN_MS
  ------------------
  |  | 8622|      0|#define MG_TCPIP_FIN_MS 1000   // Timeout for closing connection
  ------------------
  |  Branch (8981:18): [True: 0, False: 4.99k]
  ------------------
 8982|  4.99k|                                       : MG_TCPIP_KEEPALIVE_MS;
  ------------------
  |  | 8616|  15.5k|#define MG_TCPIP_KEEPALIVE_MS 45000  // TCP keep-alive period, ms
  ------------------
 8983|  10.5k|  if (s->ttype == MIP_TTYPE_FIN) return;  // skip if 3-way closing
  ------------------
  |  | 8657|  10.5k|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
  |  Branch (8983:7): [True: 0, False: 10.5k]
  ------------------
 8984|  10.5k|  s->timer = ifp->now + n;
 8985|  10.5k|  s->ttype = type;
 8986|  10.5k|  MG_VERBOSE(("%lu %d -> %llx", c->id, type, s->timer));
  ------------------
  |  | 1826|  10.5k|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1813|  10.5k|  do {                      \
  |  |  |  | 1814|  10.5k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 10.5k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  10.5k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 10.5k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 8987|  10.5k|}
fuzz.c:_ZL10close_connP13mg_connection:
10893|  5.57k|static void close_conn(struct mg_connection *c) {
10894|  5.57k|  struct connstate *s = (struct connstate *) (c + 1);
10895|  5.57k|  mg_iobuf_free(&s->txq);
10896|  5.57k|  mg_close_conn(c);
10897|  5.57k|}
fuzz.c:_ZL15l2addr_resolvedP13mg_connection:
10913|  5.57k|static void l2addr_resolved(struct mg_connection *c) {
10914|  5.57k|  if (c->is_udp) {
  ------------------
  |  Branch (10914:7): [True: 0, False: 5.57k]
  ------------------
10915|      0|    c->is_connecting = 0;
10916|      0|    mg_call(c, MG_EV_CONNECT, NULL);
10917|  5.57k|  } else {
10918|  5.57k|    send_syn(c);
10919|  5.57k|    settmout(c, MIP_TTYPE_SYN);
  ------------------
  |  | 8656|  5.57k|#define MIP_TTYPE_SYN 3        // SYN sent, waiting for response
  ------------------
10920|  5.57k|  }
10921|  5.57k|}
fuzz.c:_ZL8send_synP13mg_connection:
10906|  5.57k|static void send_syn(struct mg_connection *c) {
10907|  5.57k|  struct connstate *s = (struct connstate *) (c + 1);
10908|  5.57k|  uint32_t isn = mg_htonl((uint32_t) mg_ntohs(c->loc.port));
  ------------------
  |  | 2095|  5.57k|#define mg_htonl(x) mg_ntohl(x)
  ------------------
10909|  5.57k|  tx_tcp(c->mgr->ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_SYN, isn, 0,
  ------------------
  |  | 8745|  5.57k|#define TH_SYN 0x02
  ------------------
10910|  5.57k|         MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 8629|  5.57k|#define MG_TCPIP_WIN 6000  // TCP window size
  ------------------
10911|  5.57k|}
fuzz.c:_ZL13mg_tcpip_pollP11mg_tcpip_ifm:
10721|  5.57k|static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
10722|  5.57k|  struct mg_connection *c;
10723|  5.57k|  bool expired_1000ms = mg_timer_expired(&ifp->timer_1000ms, 1000, now);
10724|  5.57k|  ifp->now = now;
10725|       |
10726|  5.57k|  if (expired_1000ms) {
  ------------------
  |  Branch (10726:7): [True: 5.57k, False: 0]
  ------------------
10727|       |#if MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
10728|       |    const char *names[] = {"down", "lnk up", "lnk rdy", "req", "ip", "ready"};
10729|       |    size_t max = sizeof(names) / sizeof(char *);
10730|       |    unsigned int state = ifp->state >= max ? max - 1 : ifp->state;
10731|       |    MG_INFO(("Status: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u", names[state],
10732|       |             mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent, ifp->ndrop,
10733|       |             ifp->nerr));
10734|       |#if MG_ENABLE_IPV6
10735|       |    state = ifp->state6 >= max ? max - 1 : ifp->state6;
10736|       |    if (state > MG_TCPIP_STATE_UP)
10737|       |      MG_INFO(("Status: %s, IPv6: %M", names[state], mg_print_ip6, &ifp->ip6));
10738|       |#endif
10739|       |#endif
10740|  5.57k|    backlog_poll(ifp->mgr);
10741|  5.57k|  }
10742|       |  // Handle gw ARP request timeout, order is important
10743|  5.57k|  if (expired_1000ms && ifp->state == MG_TCPIP_STATE_IP) {
  ------------------
  |  | 4739|  5.57k|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
  |  Branch (10743:7): [True: 5.57k, False: 0]
  |  Branch (10743:25): [True: 0, False: 5.57k]
  ------------------
10744|      0|    ifp->state = MG_TCPIP_STATE_READY;  // keep best-effort MAC or poison mark
  ------------------
  |  | 4740|      0|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
10745|      0|    onstatechange(ifp);
10746|      0|  }
10747|  5.57k|  if (expired_1000ms && ifp->state == MG_TCPIP_STATE_READY && !ifp->gw_ready &&
  ------------------
  |  | 4740|  11.1k|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
  |  Branch (10747:7): [True: 5.57k, False: 0]
  |  Branch (10747:25): [True: 5.57k, False: 0]
  |  Branch (10747:63): [True: 0, False: 5.57k]
  ------------------
10748|      0|      ifp->gw != 0)
  ------------------
  |  Branch (10748:7): [True: 0, False: 0]
  ------------------
10749|      0|    mg_tcpip_arp_request(ifp, ifp->gw, NULL);  // retry GW ARP request
10750|       |#if MG_ENABLE_IPV6
10751|       |  // Handle gw NS/NA req/resp timeout, order is important
10752|       |  if (expired_1000ms && ifp->state6 == MG_TCPIP_STATE_IP) {
10753|       |    ifp->state6 = MG_TCPIP_STATE_READY;  // keep best-effort MAC or poison mark
10754|       |    onstate6change(ifp);
10755|       |  }
10756|       |  if (expired_1000ms && ifp->state == MG_TCPIP_STATE_READY && !ifp->gw6_ready &&
10757|       |      (ifp->gw6[0] != 0 || ifp->gw6[1] != 0))
10758|       |    tx_ndp_ns(ifp, ifp->gw6, NULL);  // retry GW hwaddr resolution
10759|       |#endif
10760|       |
10761|  5.57k|  {  // poll driver and let L2 do its work, if any
10762|       |    // Handle physical interface up/down status
10763|  5.57k|    bool drv_up, l2_up;
10764|  5.57k|    drv_up = ifp->driver->poll ? ifp->driver->poll(ifp, expired_1000ms) : true;
  ------------------
  |  Branch (10764:14): [True: 5.57k, False: 0]
  ------------------
10765|  5.57k|    l2_up = mg_l2_poll(ifp, expired_1000ms);  // Handle L2 up/down link status;
10766|  5.57k|    if (expired_1000ms) {                     // ifp->state rules over state6
  ------------------
  |  Branch (10766:9): [True: 5.57k, False: 0]
  ------------------
10767|  5.57k|      mg_ip_link(ifp, drv_up, l2_up);         // Handle IPv4
10768|  5.57k|      mg_ip6_link(ifp, drv_up, l2_up);        // Handle IPv6
10769|  5.57k|      if (ifp->state < MG_TCPIP_STATE_UP) MG_ERROR(("Network is down"));
  ------------------
  |  | 4737|  5.57k|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
                    if (ifp->state < MG_TCPIP_STATE_UP) MG_ERROR(("Network is down"));
  ------------------
  |  | 1823|    585|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|    585|  do {                      \
  |  |  |  | 1814|    585|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 585]
  |  |  |  |  ------------------
  |  |  |  | 1815|    585|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 585]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (10769:11): [True: 585, False: 4.99k]
  ------------------
10770|  5.57k|      mg_tcpip_call(ifp, MG_TCPIP_EV_TIMER_1S, NULL);
10771|  5.57k|    }
10772|  5.57k|  }
10773|       |
10774|  5.57k|  mg_ip_poll(ifp, expired_1000ms);   // Handle IPv4
10775|  5.57k|  mg_ip6_poll(ifp, expired_1000ms);  // Handle IPv6
10776|       |
10777|       |  // Read data from the network (mg_tcpip_rx() will discard for us)
10778|  5.57k|  if (ifp->driver->rx != NULL) {  // Simple polling driver, returns one frame
  ------------------
  |  Branch (10778:7): [True: 5.57k, False: 0]
  ------------------
10779|  5.57k|    size_t len =
10780|  5.57k|        ifp->driver->rx(ifp->recv_queue.buf, ifp->recv_queue.size, ifp);
10781|  5.57k|    if (len > 0) {
  ------------------
  |  Branch (10781:9): [True: 0, False: 5.57k]
  ------------------
10782|      0|      ifp->nrecv++;
10783|      0|      mg_tcpip_rx(ifp, ifp->recv_queue.buf, len);
10784|      0|    }
10785|  5.57k|  } else {  // Complex poll / Interrupt-based driver. Queues recvd frames
10786|      0|    char *buf;
10787|      0|    size_t len, cnt = 7;  // Max 7 packets to fetch
10788|      0|    while (cnt-- > 0 && (len = mg_queue_next(&ifp->recv_queue, &buf)) > 0) {
  ------------------
  |  Branch (10788:12): [True: 0, False: 0]
  |  Branch (10788:25): [True: 0, False: 0]
  ------------------
10789|      0|      mg_tcpip_rx(ifp, buf, len);
10790|      0|      mg_queue_del(&ifp->recv_queue, len);
10791|      0|    }
10792|      0|  }
10793|  5.57k|  if (ifp->state < MG_TCPIP_STATE_UP) return;  // need to let L2 do its job
  ------------------
  |  | 4737|  5.57k|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (10793:7): [True: 585, False: 4.99k]
  ------------------
10794|       |
10795|       |  // Process timeouts
10796|  9.98k|  for (c = ifp->mgr->conns; c != NULL; c = c->next) {
  ------------------
  |  Branch (10796:29): [True: 4.99k, False: 4.99k]
  ------------------
10797|  4.99k|    struct connstate *s = (struct connstate *) (c + 1);
10798|  4.99k|    if ((c->is_udp && !c->is_arplooking) || c->is_listening || c->is_resolving)
  ------------------
  |  Branch (10798:10): [True: 0, False: 4.99k]
  |  Branch (10798:23): [True: 0, False: 0]
  |  Branch (10798:45): [True: 0, False: 4.99k]
  |  Branch (10798:64): [True: 0, False: 4.99k]
  ------------------
10799|      0|      continue;
10800|  4.99k|    if (!c->is_full && s->is_full) {
  ------------------
  |  Branch (10800:9): [True: 4.99k, False: 0]
  |  Branch (10800:24): [True: 0, False: 4.99k]
  ------------------
10801|       |      // Application resumed the connection: advertise the restored window
10802|      0|      s->is_full = false;
10803|      0|      tx_tcp(ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_ACK, mg_htonl(s->seq),
  ------------------
  |  | 8748|      0|#define TH_ACK 0x10
  ------------------
                    tx_tcp(ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_ACK, mg_htonl(s->seq),
  ------------------
  |  | 2095|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
10804|      0|             mg_htonl(s->ack), MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 2095|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
                           mg_htonl(s->ack), MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 8629|      0|#define MG_TCPIP_WIN 6000  // TCP window size
  ------------------
10805|      0|    }
10806|  4.99k|    if (s->retransmit && s->txq.len > 0 && ifp->now > s->txq_timer) {
  ------------------
  |  Branch (10806:9): [True: 0, False: 4.99k]
  |  Branch (10806:26): [True: 0, False: 0]
  |  Branch (10806:44): [True: 0, False: 0]
  ------------------
10807|      0|      if (s->txq_retries < 255) s->txq_retries++;
  ------------------
  |  Branch (10807:11): [True: 0, False: 0]
  ------------------
10808|       |      // R1 reports a delivery problem; it does not close (RFC-9293, 3.8.3).
10809|      0|      if (s->txq_retries == MG_TCPIP_RTX_R1)
  ------------------
  |  | 8625|      0|#define MG_TCPIP_RTX_R1 3  // Delivery-problem threshold (RFC-9293, 3.8.3)
  ------------------
  |  Branch (10809:11): [True: 0, False: 0]
  ------------------
10810|      0|        MG_ERROR(("%lu retransmit", c->id));
  ------------------
  |  | 1823|      0|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10811|      0|      retransmit(c);
10812|      0|    }
10813|  4.99k|    if (ifp->now > s->timer) {
  ------------------
  |  Branch (10813:9): [True: 4.99k, False: 0]
  ------------------
10814|  4.99k|      if (s->ttype == MIP_TTYPE_ARP) {
  ------------------
  |  | 8655|  4.99k|#define MIP_TTYPE_ARP 2        // ARP resolve sent, waiting for response
  ------------------
  |  Branch (10814:11): [True: 0, False: 4.99k]
  ------------------
10815|      0|        proto_error(c, false, "ARP timeout");
10816|  4.99k|      } else if (c->is_udp) {
  ------------------
  |  Branch (10816:18): [True: 0, False: 4.99k]
  ------------------
10817|      0|        continue;
10818|  4.99k|      } else if (s->ttype == MIP_TTYPE_ACK && s->acked != s->ack) {
  ------------------
  |  | 8654|  9.98k|#define MIP_TTYPE_ACK 1        // Peer sent us data, we have to ack it soon
  ------------------
  |  Branch (10818:18): [True: 0, False: 4.99k]
  |  Branch (10818:47): [True: 0, False: 0]
  ------------------
10819|      0|        MG_VERBOSE(("%lu ack %x %x", c->id, s->seq, s->ack));
  ------------------
  |  | 1826|      0|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10820|      0|        tx_tcp(ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_ACK, mg_htonl(s->seq),
  ------------------
  |  | 8748|      0|#define TH_ACK 0x10
  ------------------
                      tx_tcp(ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_ACK, mg_htonl(s->seq),
  ------------------
  |  | 2095|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
10821|      0|               mg_htonl(s->ack), s->is_full ? 0 : MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 2095|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
                             mg_htonl(s->ack), s->is_full ? 0 : MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 8629|      0|#define MG_TCPIP_WIN 6000  // TCP window size
  ------------------
  |  Branch (10821:34): [True: 0, False: 0]
  ------------------
10822|      0|        s->acked = s->ack;
10823|  4.99k|      } else if (s->ttype == MIP_TTYPE_SYN) {
  ------------------
  |  | 8656|  4.99k|#define MIP_TTYPE_SYN 3        // SYN sent, waiting for response
  ------------------
  |  Branch (10823:18): [True: 4.99k, False: 0]
  ------------------
10824|  4.99k|        proto_error(c, false, "Connection timeout");
10825|  4.99k|      } else if (s->ttype == MIP_TTYPE_FIN) {
  ------------------
  |  | 8657|      0|#define MIP_TTYPE_FIN 4  // FIN sent, waiting until terminating the connection
  ------------------
  |  Branch (10825:18): [True: 0, False: 0]
  ------------------
10826|      0|        s->is_closing = 1;
10827|      0|        continue;
10828|      0|      } else {
10829|      0|        if (s->tmiss++ > 2) {
  ------------------
  |  Branch (10829:13): [True: 0, False: 0]
  ------------------
10830|      0|          proto_error(c, false, "keepalive");
10831|      0|        } else {
10832|      0|          MG_VERBOSE(("%lu keepalive", c->id));
  ------------------
  |  | 1826|      0|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10833|      0|          tx_tcp(ifp, s->mac, &c->loc, &c->rem, c->dscp, TH_ACK,
  ------------------
  |  | 8748|      0|#define TH_ACK 0x10
  ------------------
10834|      0|                 mg_htonl(s->seq - 1), mg_htonl(s->ack),
  ------------------
  |  | 2095|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
                               mg_htonl(s->seq - 1), mg_htonl(s->ack),
  ------------------
  |  | 2095|      0|#define mg_htonl(x) mg_ntohl(x)
  ------------------
10835|      0|                 s->is_full ? 0 : MG_TCPIP_WIN, NULL, 0);
  ------------------
  |  | 8629|      0|#define MG_TCPIP_WIN 6000  // TCP window size
  ------------------
  |  Branch (10835:18): [True: 0, False: 0]
  ------------------
10836|      0|        }
10837|      0|      }
10838|       |
10839|  4.99k|      settmout(c, MIP_TTYPE_KEEPALIVE);
  ------------------
  |  | 8653|  4.99k|#define MIP_TTYPE_KEEPALIVE 0  // Connection is idle for long, send keepalive
  ------------------
10840|  4.99k|    }
10841|  4.99k|  }
10842|  4.99k|}
fuzz.c:_ZL12backlog_pollP6mg_mgr:
10324|  5.57k|static void backlog_poll(struct mg_mgr *mgr) {
10325|  5.57k|  struct mg_connection *c = NULL;
10326|  11.1k|  for (c = mgr->conns; c != NULL; c = c->next) {
  ------------------
  |  Branch (10326:24): [True: 5.57k, False: 5.57k]
  ------------------
10327|  5.57k|    if (!c->is_udp && c->is_listening) backlog_maintain(c);
  ------------------
  |  Branch (10327:9): [True: 5.57k, False: 0]
  |  Branch (10327:23): [True: 0, False: 5.57k]
  ------------------
10328|  5.57k|  }
10329|  5.57k|}
fuzz.c:_ZL13onstatechangeP11mg_tcpip_if:
 9010|    585|static void onstatechange(struct mg_tcpip_if *ifp) {
 9011|    585|  if (ifp->state == MG_TCPIP_STATE_IP &&
  ------------------
  |  | 4739|  1.17k|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
  |  Branch (9011:7): [True: 0, False: 585]
  ------------------
 9012|      0|      (ifp->l2type == MG_TCPIP_L2_PPP || ifp->l2type == MG_TCPIP_L2_PPPoE))
  ------------------
  |  Branch (9012:8): [True: 0, False: 0]
  |  Branch (9012:42): [True: 0, False: 0]
  ------------------
 9013|      0|    ifp->state = MG_TCPIP_STATE_READY;
  ------------------
  |  | 4740|      0|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
 9014|    585|  if (ifp->state == MG_TCPIP_STATE_READY) {
  ------------------
  |  | 4740|    585|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
  |  Branch (9014:7): [True: 0, False: 585]
  ------------------
 9015|      0|    MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip));
  ------------------
  |  | 1824|      0|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 9016|      0|    MG_INFO(("       GW: %M", mg_print_ip4, &ifp->gw));
  ------------------
  |  | 1824|      0|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 9017|      0|    if (ifp->l2type == MG_TCPIP_L2_ETH ||
  ------------------
  |  Branch (9017:9): [True: 0, False: 0]
  ------------------
 9018|      0|        ifp->l2type == MG_TCPIP_L2_PPPoE)  // TODO(): print other l2
  ------------------
  |  Branch (9018:9): [True: 0, False: 0]
  ------------------
 9019|      0|      MG_INFO(("      MAC: %M", mg_print_mac, ifp->mac));
  ------------------
  |  | 1824|      0|#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 9020|      0|    if (ifp->l2type == MG_TCPIP_L2_ETH)
  ------------------
  |  Branch (9020:9): [True: 0, False: 0]
  ------------------
 9021|      0|      mg_tcpip_arp_request(ifp, ifp->ip, ifp->mac);  // gratuitous ARP annc
 9022|      0|    if (ifp->is_ip_changed) {
  ------------------
  |  Branch (9022:9): [True: 0, False: 0]
  ------------------
 9023|      0|      struct mg_connection *c;
 9024|      0|      for (c = ifp->mgr->conns; c != NULL; c = c->next) {
  ------------------
  |  Branch (9024:33): [True: 0, False: 0]
  ------------------
 9025|      0|        if (!c->is_listening && !c->is_udp) c->is_closing = 1;
  ------------------
  |  Branch (9025:13): [True: 0, False: 0]
  |  Branch (9025:33): [True: 0, False: 0]
  ------------------
 9026|      0|      }
 9027|      0|      ifp->is_ip_changed = false;
 9028|      0|    }
 9029|    585|  } else if (ifp->state == MG_TCPIP_STATE_IP) {
  ------------------
  |  | 4739|    585|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
  |  Branch (9029:14): [True: 0, False: 585]
  ------------------
 9030|      0|    if (ifp->gw != 0 && ifp->l2type == MG_TCPIP_L2_ETH)
  ------------------
  |  Branch (9030:9): [True: 0, False: 0]
  |  Branch (9030:25): [True: 0, False: 0]
  ------------------
 9031|      0|      mg_tcpip_arp_request(ifp, ifp->gw, NULL);  // unsolicited GW ARP request
 9032|    585|  } else if (ifp->state == MG_TCPIP_STATE_UP) {
  ------------------
  |  | 4737|    585|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (9032:14): [True: 0, False: 585]
  ------------------
 9033|      0|    srand((unsigned int) mg_millis());
 9034|      0|  }
 9035|    585|  mg_tcpip_call(ifp, MG_TCPIP_EV_STATE_CHANGE, &ifp->state);
 9036|    585|}
fuzz.c:_ZL10mg_ip_linkP11mg_tcpip_ifbb:
10661|  5.57k|static void mg_ip_link(struct mg_tcpip_if *ifp, bool drv_up, bool l2_up) {
10662|  5.57k|  bool cur_drv = (ifp->state != MG_TCPIP_STATE_DOWN);
  ------------------
  |  | 4735|  5.57k|#define MG_TCPIP_STATE_DOWN 0       // Physical link is down
  ------------------
10663|  5.57k|  bool cur_l2 = (ifp->state >= MG_TCPIP_STATE_UP);
  ------------------
  |  | 4737|  5.57k|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
10664|  5.57k|  if (!l2_up && ifp->enable_dhcp_client) ifp->ip = 0;
  ------------------
  |  Branch (10664:7): [True: 585, False: 4.99k]
  |  Branch (10664:17): [True: 0, False: 585]
  ------------------
10665|  5.57k|  if (drv_up != cur_drv || l2_up != cur_l2) {  // link/L2 state has changed
  ------------------
  |  Branch (10665:7): [True: 0, False: 5.57k]
  |  Branch (10665:28): [True: 585, False: 4.99k]
  ------------------
10666|    585|    ifp->state = !drv_up  ? MG_TCPIP_STATE_DOWN
  ------------------
  |  | 4735|      0|#define MG_TCPIP_STATE_DOWN 0       // Physical link is down
  ------------------
  |  Branch (10666:18): [True: 0, False: 585]
  ------------------
10667|    585|                 : !l2_up ? MG_TCPIP_STATE_LINK_UP
  ------------------
  |  | 4736|    585|#define MG_TCPIP_STATE_LINK_UP 1    // Driver reports physical link is up
  ------------------
  |  Branch (10667:20): [True: 585, False: 0]
  ------------------
10668|    585|                 : ifp->enable_dhcp_client || ifp->ip == 0 ? MG_TCPIP_STATE_UP
  ------------------
  |  | 4737|      0|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (10668:20): [True: 0, False: 0]
  |  Branch (10668:47): [True: 0, False: 0]
  ------------------
10669|      0|                                                           : MG_TCPIP_STATE_IP;
  ------------------
  |  | 4739|    585|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
10670|    585|    onstatechange(ifp);
10671|  4.99k|  } else if (!ifp->enable_dhcp_client && ifp->state == MG_TCPIP_STATE_UP &&
  ------------------
  |  | 4737|  9.98k|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (10671:14): [True: 4.99k, False: 0]
  |  Branch (10671:42): [True: 0, False: 4.99k]
  ------------------
10672|      0|             ifp->ip) {
  ------------------
  |  Branch (10672:14): [True: 0, False: 0]
  ------------------
10673|      0|    ifp->state = MG_TCPIP_STATE_IP;  // ifp->fn has set an IP
  ------------------
  |  | 4739|      0|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
10674|      0|    onstatechange(ifp);
10675|      0|  }
10676|  5.57k|}
fuzz.c:_ZL13mg_tcpip_callP11mg_tcpip_ifiPv:
 8841|  6.17k|static void mg_tcpip_call(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
 8842|       |#if 0 && MG_ENABLE_PROFILE
 8843|       |  const char *names[] = {"TCPIP_EV_STATE_CHANGE",  "TCPIP_EV_DHCP_DNS",
 8844|       |                         "TCPIP_EV_DHCP_SNTP",     "TCPIP_EV_ARP",
 8845|       |                         "TCPIP_EV_TIMER_1S",      "TCPIP_EV_WIFI_SCAN_RESULT",
 8846|       |                         "TCPIP_EV_WIFI_SCAN_END", "TCPIP_EV_WIFI_CONNECT_ERR",
 8847|       |                         "TCPIP_EV_DRIVER",        "TCPIP_EV_STATE6_CHANGE",
 8848|       |                         "TCPIP_EV_USER"};
 8849|       |  if (ev != MG_TCPIP_EV_TIMER_1S && ev < (int) (sizeof(names) / sizeof(names[0]))) {
 8850|       |    MG_PROF_ADD(ifp, names[ev]); // TODO(): call MG_PROF_DUMP() MG_PROF_FREE()
 8851|       |  }
 8852|       |#endif
 8853|       |  // Fire protocol handler first, user handler second. See #2559
 8854|  6.17k|  if (ifp->pfn != NULL) ifp->pfn(ifp, ev, ev_data);
  ------------------
  |  Branch (8854:7): [True: 0, False: 6.17k]
  ------------------
 8855|  6.17k|  if (ifp->fn != NULL) ifp->fn(ifp, ev, ev_data);
  ------------------
  |  Branch (8855:7): [True: 0, False: 6.17k]
  ------------------
 8856|  6.17k|}
fuzz.c:_ZL10mg_ip_pollP11mg_tcpip_ifb:
10640|  5.57k|static void mg_ip_poll(struct mg_tcpip_if *ifp, bool s1) {
10641|  5.57k|  if (ifp->state < MG_TCPIP_STATE_UP) return;
  ------------------
  |  | 4737|  5.57k|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (10641:7): [True: 585, False: 4.99k]
  ------------------
10642|       |  // DHCP RFC-2131 (4.4)
10643|  4.99k|  if (ifp->enable_dhcp_client && s1) {
  ------------------
  |  Branch (10643:7): [True: 0, False: 4.99k]
  |  Branch (10643:34): [True: 0, False: 0]
  ------------------
10644|      0|    if (ifp->state == MG_TCPIP_STATE_UP) {
  ------------------
  |  | 4737|      0|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (10644:9): [True: 0, False: 0]
  ------------------
10645|      0|      tx_dhcp_discover(ifp);  // INIT (4.4.1)
10646|      0|    } else if (ifp->state == MG_TCPIP_STATE_READY &&
  ------------------
  |  | 4740|      0|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
  |  Branch (10646:16): [True: 0, False: 0]
  ------------------
10647|      0|               ifp->lease_expire > 0) {  // BOUND / RENEWING / REBINDING
  ------------------
  |  Branch (10647:16): [True: 0, False: 0]
  ------------------
10648|      0|      if (ifp->now >= ifp->lease_expire) {
  ------------------
  |  Branch (10648:11): [True: 0, False: 0]
  ------------------
10649|      0|        ifp->state = MG_TCPIP_STATE_UP, ifp->ip = 0;  // expired, release IP
  ------------------
  |  | 4737|      0|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
10650|      0|        onstatechange(ifp);
10651|      0|      } else if (ifp->now + 30UL * 60UL * 1000UL > ifp->lease_expire &&
  ------------------
  |  Branch (10651:18): [True: 0, False: 0]
  ------------------
10652|      0|                 ((ifp->now / 1000) % 60) == 0) {
  ------------------
  |  Branch (10652:18): [True: 0, False: 0]
  ------------------
10653|       |        // hack: 30 min before deadline, try to rebind (4.3.6) every min
10654|      0|        tx_dhcp_request_re(
10655|       |            ifp, mg_l2_mapip(ifp->l2type, MG_TCPIP_L2ADDR_BCAST, NULL), ifp->ip,
10656|      0|            0xffffffff);
10657|      0|      }  // TODO(): Handle T1 (RENEWING) and T2 (REBINDING) (4.4.5)
10658|      0|    }
10659|      0|  }
10660|  4.99k|}
fuzz.c:_ZL11proto_errorP13mg_connectionbPKcz:
 9802|  4.99k|static void proto_error(struct mg_connection *c, bool r, const char *f, ...) {
 9803|  4.99k|  char buf[64];
 9804|  4.99k|  va_list ap;
 9805|  4.99k|  struct connstate *s = (struct connstate *) (c + 1);
 9806|  4.99k|  va_start(ap, f);
 9807|  4.99k|  mg_vsnprintf(buf, sizeof(buf), f, &ap);
 9808|  4.99k|  va_end(ap);
 9809|  4.99k|  MG_ERROR(("%lu %ld %s", c->id, c->fd, buf));
  ------------------
  |  | 1823|  4.99k|#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
  |  |  ------------------
  |  |  |  | 1813|  4.99k|  do {                      \
  |  |  |  | 1814|  4.99k|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 4.99k]
  |  |  |  |  ------------------
  |  |  |  | 1815|  4.99k|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 4.99k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 9810|  4.99k|  c->is_closing = 1;  // Stop Mongoose I/O
 9811|  4.99k|  s->is_closing = 1;  // Transport-terminal; do not send FIN
 9812|  4.99k|  if (r && !c->is_udp) s->send_rst = true;  // honot TCP RST request
  ------------------
  |  Branch (9812:7): [True: 0, False: 4.99k]
  |  Branch (9812:12): [True: 0, False: 0]
  ------------------
 9813|  4.99k|  mg_call(c, MG_EV_ERROR, buf);
 9814|  4.99k|}
fuzz.c:_ZL20mg_pfn_iobuf_privatecPvb:
13687|  23.1M|static void mg_pfn_iobuf_private(char ch, void *param, bool expand) {
13688|  23.1M|  struct mg_iobuf *io = (struct mg_iobuf *) param;
13689|  23.1M|  if (expand && io->len + 2 > io->size) mg_iobuf_resize(io, io->len + 2);
  ------------------
  |  Branch (13689:7): [True: 13.9M, False: 9.18M]
  |  Branch (13689:17): [True: 1.83k, False: 13.9M]
  ------------------
13690|  23.1M|  if (io->len + 2 <= io->size) {
  ------------------
  |  Branch (13690:7): [True: 23.1M, False: 2.45k]
  ------------------
13691|  23.1M|    io->buf[io->len++] = (uint8_t) ch;
13692|  23.1M|    io->buf[io->len] = 0;
13693|  23.1M|  } else if (io->len < io->size) {
  ------------------
  |  Branch (13693:14): [True: 1.03k, False: 1.42k]
  ------------------
13694|  1.03k|    io->buf[io->len++] = 0;  // Guarantee to 0-terminate
13695|  1.03k|  }
13696|  23.1M|}
fuzz.c:_ZL12gettimestampPKj:
14715|    552|static int64_t gettimestamp(const uint32_t *data) {
14716|    552|  uint32_t sec = mg_ntohl(data[0]), frac = mg_ntohl(data[1]);
14717|    552|  if (sec) sec -= SNTP_TIME_OFFSET;
  ------------------
  |  |14706|    529|#define SNTP_TIME_OFFSET 2208988800U  // (1970 - 1900) in seconds
  ------------------
  |  Branch (14717:7): [True: 529, False: 23]
  ------------------
14718|    552|  return ((int64_t) sec) * 1000 + (int64_t) (frac / SNTP_MAX_FRAC * 1000.0);
  ------------------
  |  |14707|    552|#define SNTP_MAX_FRAC 4294967295.0    // 2 ** 32 - 1
  ------------------
14719|    552|}
fuzz.c:_ZL7mg_tolcc:
15733|  2.17M|static int mg_tolc(char c) {
15734|  2.17M|  return (c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : c;
  ------------------
  |  Branch (15734:11): [True: 2.03M, False: 141k]
  |  Branch (15734:23): [True: 1.27M, False: 761k]
  ------------------
15735|  2.17M|}
fuzz.c:_ZL8urlparsePKc:
28780|  11.1k|static struct url urlparse(const char *url) {
28781|  11.1k|  size_t i;
28782|  11.1k|  struct url u;
28783|  11.1k|  memset(&u, 0, sizeof(u));
28784|   256k|  for (i = 0; url[i] != '\0'; i++) {
  ------------------
  |  Branch (28784:15): [True: 245k, False: 11.1k]
  ------------------
28785|   245k|    if (url[i] == '/' && i > 0 && u.host == 0 && url[i - 1] == '/') {
  ------------------
  |  Branch (28785:9): [True: 22.3k, False: 223k]
  |  Branch (28785:26): [True: 22.3k, False: 0]
  |  Branch (28785:35): [True: 22.3k, False: 0]
  |  Branch (28785:50): [True: 11.1k, False: 11.1k]
  ------------------
28786|  11.1k|      u.host = i + 1;
28787|  11.1k|      u.port = 0;
28788|   234k|    } else if (url[i] == ']') {
  ------------------
  |  Branch (28788:16): [True: 0, False: 234k]
  ------------------
28789|      0|      u.port = 0;  // IPv6 URLs, like http://[::1]/bar
28790|   234k|    } else if (url[i] == ':' && u.port == 0 && u.uri == 0) {
  ------------------
  |  Branch (28790:16): [True: 22.3k, False: 211k]
  |  Branch (28790:33): [True: 22.3k, False: 0]
  |  Branch (28790:48): [True: 22.3k, False: 0]
  ------------------
28791|  22.3k|      u.port = i + 1;
28792|   211k|    } else if (url[i] == '@' && u.user == 0 && u.pass == 0 && u.uri == 0) {
  ------------------
  |  Branch (28792:16): [True: 0, False: 211k]
  |  Branch (28792:33): [True: 0, False: 0]
  |  Branch (28792:48): [True: 0, False: 0]
  |  Branch (28792:63): [True: 0, False: 0]
  ------------------
28793|      0|      u.user = u.host;
28794|      0|      u.pass = u.port;
28795|      0|      u.host = i + 1;
28796|      0|      u.port = 0;
28797|   211k|    } else if (url[i] == '/' && u.host && u.uri == 0) {
  ------------------
  |  Branch (28797:16): [True: 11.1k, False: 200k]
  |  Branch (28797:33): [True: 0, False: 11.1k]
  |  Branch (28797:43): [True: 0, False: 0]
  ------------------
28798|      0|      u.uri = i;
28799|      0|    }
28800|   245k|  }
28801|  11.1k|  u.end = i;
28802|       |#if 0
28803|       |  printf("[%s] %d %d %d %d %d\n", url, u.user, u.pass, u.host, u.port, u.uri);
28804|       |#endif
28805|  11.1k|  return u;
28806|  11.1k|}
fuzz.c:_ZL11mg_tcpip_rxP11mg_tcpip_ifPvm:
10617|  5.57k|static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) {
10618|  5.57k|  struct pkt pkt;
10619|  5.57k|  enum mg_l2proto proto;
10620|  5.57k|  memset(&pkt, 0, sizeof(pkt));
10621|  5.57k|  pkt.raw.buf = (char *) buf;
10622|  5.57k|  pkt.raw.len = len;
10623|  5.57k|  pkt.l2 = (uint8_t *) pkt.raw.buf;
10624|  5.57k|  if (!mg_l2_rx(ifp, &proto, &pkt.pay, &pkt.raw)) return;
  ------------------
  |  Branch (10624:7): [True: 5.45k, False: 120]
  ------------------
10625|    120|  if (ifp->state < MG_TCPIP_STATE_UP) return;  // discard while L2 is not up
  ------------------
  |  | 4737|    120|#define MG_TCPIP_STATE_UP 2         // L2 is ready (e.g. PPP negotiated)
  ------------------
  |  Branch (10625:7): [True: 0, False: 120]
  ------------------
10626|    120|  if (proto == MG_TCPIP_L2PROTO_ARP) {
  ------------------
  |  Branch (10626:7): [True: 16, False: 104]
  ------------------
10627|     16|    pkt.arp = (struct arp *) (pkt.pay.buf);
10628|     16|    if (pkt.pay.len < sizeof(*pkt.arp)) return;  // Truncated
  ------------------
  |  Branch (10628:9): [True: 0, False: 16]
  ------------------
10629|     16|    mg_tcpip_call(ifp, MG_TCPIP_EV_ARP, &pkt.raw);
10630|     16|    rx_arp(ifp, &pkt);
10631|    104|  } else if (proto == MG_TCPIP_L2PROTO_IPV6) {
  ------------------
  |  Branch (10631:14): [True: 9, False: 95]
  ------------------
10632|      9|    pkt.ip6 = (struct ip6 *) (pkt.pay.buf);
10633|      9|    rx_ip6(ifp, &pkt);
10634|     95|  } else if (proto == MG_TCPIP_L2PROTO_IPV4) {
  ------------------
  |  Branch (10634:14): [True: 65, False: 30]
  ------------------
10635|     65|    pkt.ip = (struct ip *) (pkt.pay.buf);
10636|     65|    rx_ip(ifp, &pkt);
10637|     65|  }
10638|    120|}
fuzz.c:_ZL6rx_arpP11mg_tcpip_ifP3pkt:
 9214|     16|static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
 9215|     16|  if (pkt->arp->op == mg_htons(1) && pkt->arp->tpa == ifp->ip) {
  ------------------
  |  | 2094|     32|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (9215:7): [True: 4, False: 12]
  |  Branch (9215:38): [True: 0, False: 4]
  ------------------
 9216|       |    // ARP request. Make a response, then send
 9217|       |    // MG_VERBOSE(("ARP req from %M", mg_print_ip4, &pkt->arp->spa));
 9218|      0|    uint8_t *l2p = (uint8_t *) ifp->tx.buf;
 9219|      0|    struct arp *arp = (struct arp *) mg_l2_header(
 9220|      0|        ifp, MG_TCPIP_L2PROTO_ARP, ifp->mac, mg_l2_getaddr(ifp, pkt->l2), l2p);
 9221|      0|    *arp = *pkt->arp;
 9222|      0|    arp->op = mg_htons(2);
  ------------------
  |  | 2094|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
 9223|      0|    memcpy(arp->tha, pkt->arp->sha, sizeof(pkt->arp->tha));
 9224|      0|    memcpy(arp->sha, ifp->mac, sizeof(pkt->arp->sha));
 9225|      0|    arp->tpa = pkt->arp->spa;
 9226|      0|    arp->spa = ifp->ip;
 9227|      0|    MG_DEBUG(("ARP: tell %M we're %M", mg_print_ip4, &arp->tpa, mg_print_mac,
  ------------------
  |  | 1825|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 9228|      0|              ifp->mac));
 9229|      0|    driver_output(ifp, mg_l2_trailer(ifp, sizeof(*arp), (uint8_t *) (arp + 1)));
 9230|     16|  } else if (pkt->arp->op == mg_htons(2)) {
  ------------------
  |  | 2094|     16|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (9230:14): [True: 2, False: 14]
  ------------------
 9231|      2|    if (memcmp(pkt->arp->tha, ifp->mac, sizeof(pkt->arp->tha)) != 0) return;
  ------------------
  |  Branch (9231:9): [True: 2, False: 0]
  ------------------
 9232|       |    // MG_VERBOSE(("ARP resp from %M", mg_print_ip4, &pkt->arp->spa));
 9233|      0|    if (pkt->arp->spa == ifp->gw) {
  ------------------
  |  Branch (9233:9): [True: 0, False: 0]
  ------------------
 9234|       |      // Got response for the GW ARP request. Set ifp->gwmac and IP -> READY
 9235|      0|      memcpy(ifp->gwmac, pkt->arp->sha, sizeof(ifp->gwmac));
 9236|      0|      ifp->gw_ready = true;
 9237|      0|      if (ifp->state == MG_TCPIP_STATE_IP) {
  ------------------
  |  | 4739|      0|#define MG_TCPIP_STATE_IP 4         // IP address assigned; resolving gateway MAC
  ------------------
  |  Branch (9237:11): [True: 0, False: 0]
  ------------------
 9238|      0|        ifp->state = MG_TCPIP_STATE_READY;
  ------------------
  |  | 4740|      0|#define MG_TCPIP_STATE_READY 5      // Fully operational; gateway MAC resolved
  ------------------
 9239|      0|        onstatechange(ifp);
 9240|      0|      }
 9241|      0|    } else {
 9242|      0|      struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
 9243|      0|      if (c != NULL && c->is_arplooking) {
  ------------------
  |  Branch (9243:11): [True: 0, False: 0]
  |  Branch (9243:24): [True: 0, False: 0]
  ------------------
 9244|      0|        struct connstate *s = (struct connstate *) (c + 1);
 9245|      0|        memcpy(s->mac, pkt->arp->sha, sizeof(s->mac));
 9246|      0|        MG_DEBUG(("%lu ARP resolved %M -> %M", c->id, mg_print_ip4,
  ------------------
  |  | 1825|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 9247|      0|                  &c->rem.addr.ip4, mg_print_mac, s->mac));
 9248|      0|        c->is_arplooking = 0;
 9249|      0|        l2addr_resolved(c);
 9250|      0|      }
 9251|      0|    }
 9252|      0|  }
 9253|     16|}
fuzz.c:_ZL7getpeerP6mg_mgrP3pktb:
 9183|      1|                                     bool lsn) {
 9184|      1|  struct mg_connection *c = NULL;
 9185|      1|  for (c = mgr->conns; c != NULL; c = c->next) {
  ------------------
  |  Branch (9185:24): [True: 0, False: 1]
  ------------------
 9186|      0|    if (c->is_arplooking && pkt->arp && pkt->arp->spa == c->rem.addr.ip4) break;
  ------------------
  |  Branch (9186:9): [True: 0, False: 0]
  |  Branch (9186:29): [True: 0, False: 0]
  |  Branch (9186:41): [True: 0, False: 0]
  ------------------
 9187|       |#if MG_ENABLE_IPV6
 9188|       |    if (c->is_arplooking && pkt->icmp6 && pkt->icmp6->type == 136) {
 9189|       |      struct ndp_na *na = (struct ndp_na *) (pkt->icmp6 + 1);
 9190|       |      if (MG_IP6MATCH(na->addr, c->rem.addr.ip6)) break;
 9191|       |    }
 9192|       |#endif
 9193|      0|    if (c->is_udp && pkt->udp && c->loc.port == pkt->udp->dport &&
  ------------------
  |  Branch (9193:9): [True: 0, False: 0]
  |  Branch (9193:22): [True: 0, False: 0]
  |  Branch (9193:34): [True: 0, False: 0]
  ------------------
 9194|      0|        !(c->loc.is_ip6 ^ (pkt->ip6 != NULL)))  // IP or IPv6 to same dest
  ------------------
  |  Branch (9194:9): [True: 0, False: 0]
  ------------------
 9195|      0|      break;
 9196|      0|    if (!c->is_udp && pkt->tcp && c->loc.port == pkt->tcp->dport &&
  ------------------
  |  Branch (9196:9): [True: 0, False: 0]
  |  Branch (9196:23): [True: 0, False: 0]
  |  Branch (9196:35): [True: 0, False: 0]
  ------------------
 9197|      0|        ((lsn && c->is_listening && !(c->loc.is_ip6 ^ (pkt->ip6 != NULL))) ||
  ------------------
  |  Branch (9197:11): [True: 0, False: 0]
  |  Branch (9197:18): [True: 0, False: 0]
  |  Branch (9197:37): [True: 0, False: 0]
  ------------------
 9198|      0|         (!lsn && !c->is_listening && c->rem.port == pkt->tcp->sport &&
  ------------------
  |  Branch (9198:11): [True: 0, False: 0]
  |  Branch (9198:19): [True: 0, False: 0]
  |  Branch (9198:39): [True: 0, False: 0]
  ------------------
 9199|      0|          ((!c->loc.is_ip6 && c->rem.addr.ip4 == pkt->ip->src)
  ------------------
  |  Branch (9199:13): [True: 0, False: 0]
  |  Branch (9199:31): [True: 0, False: 0]
  ------------------
 9200|       |#if MG_ENABLE_IPV6
 9201|       |           || (c->loc.is_ip6 && MG_IP6MATCH(c->rem.addr.ip6, pkt->ip6->src))
 9202|       |#endif
 9203|      0|               ))))  // validate addr for established (not listening) conns
 9204|      0|      break;
 9205|      0|  }
 9206|      1|  return c;
 9207|      1|}
fuzz.c:_ZL5rx_ipP11mg_tcpip_ifP3pkt:
10447|     65|static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) {
10448|     65|  uint8_t ihl;
10449|     65|  uint16_t frag, len;
10450|     65|  if (pkt->pay.len < sizeof(*pkt->ip)) return;  // Truncated
  ------------------
  |  Branch (10450:7): [True: 3, False: 62]
  ------------------
10451|     62|  if ((pkt->ip->ver >> 4) != 4) return;         // Not IP
  ------------------
  |  Branch (10451:7): [True: 2, False: 60]
  ------------------
10452|     60|  ihl = pkt->ip->ver & 0x0F;
10453|     60|  if (ihl < 5) return;                              // bad IHL
  ------------------
  |  Branch (10453:7): [True: 12, False: 48]
  ------------------
10454|     48|  if (pkt->pay.len < (uint16_t) (ihl * 4)) return;  // Truncated / malformed
  ------------------
  |  Branch (10454:7): [True: 14, False: 34]
  ------------------
10455|       |  // There can be link padding, take length from IP header
10456|     34|  len = mg_ntohs(pkt->ip->len);  // IP datagram length
10457|     34|  if (len < (uint16_t) (ihl * 4) || len > pkt->pay.len) return;  // malformed
  ------------------
  |  Branch (10457:7): [True: 3, False: 31]
  |  Branch (10457:37): [True: 12, False: 19]
  ------------------
10458|     19|  pkt->pay.len = len;                      // strip padding
10459|     19|  mkpay(pkt, (uint32_t *) pkt->ip + ihl);  // account for opts
10460|     19|  if (!ipcsum_ok(pkt->ip)) return;
  ------------------
  |  Branch (10460:7): [True: 11, False: 8]
  ------------------
10461|      8|  frag = mg_ntohs(pkt->ip->frag);
10462|      8|  if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) {
  ------------------
  |  | 8682|     16|#define IP_MORE_FRAGS_MSK 0x2000
  ------------------
                if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) {
  ------------------
  |  | 8681|      7|#define IP_FRAG_OFFSET_MSK 0x1fff
  ------------------
  |  Branch (10462:7): [True: 1, False: 7]
  |  Branch (10462:35): [True: 0, False: 7]
  ------------------
10463|      1|    struct mg_connection *c;
10464|      1|    if (pkt->ip->proto == 17) pkt->udp = (struct udp *) (pkt->pay.buf);
  ------------------
  |  Branch (10464:9): [True: 0, False: 1]
  ------------------
10465|      1|    if (pkt->ip->proto == 6) pkt->tcp = (struct tcp *) (pkt->pay.buf);
  ------------------
  |  Branch (10465:9): [True: 0, False: 1]
  ------------------
10466|      1|    c = getpeer(ifp->mgr, pkt, false);
10467|      1|    if (c) proto_error(c, false, "Received fragmented packet");
  ------------------
  |  Branch (10467:9): [True: 0, False: 1]
  ------------------
10468|      7|  } else if (pkt->ip->proto == 1) {
  ------------------
  |  Branch (10468:14): [True: 7, False: 0]
  ------------------
10469|      7|    pkt->icmp = (struct icmp *) (pkt->pay.buf);
10470|      7|    if (pkt->pay.len < sizeof(*pkt->icmp)) return;
  ------------------
  |  Branch (10470:9): [True: 0, False: 7]
  ------------------
10471|      7|    mkpay(pkt, pkt->icmp + 1);
10472|      7|    rx_icmp(ifp, pkt);
10473|      7|  } else if (pkt->ip->proto == 17) {
  ------------------
  |  Branch (10473:14): [True: 0, False: 0]
  ------------------
10474|      0|    pkt->udp = (struct udp *) (pkt->pay.buf);
10475|      0|    if (pkt->pay.len < sizeof(*pkt->udp)) return;  // truncated
  ------------------
  |  Branch (10475:9): [True: 0, False: 0]
  ------------------
10476|       |    // Take length from UDP header
10477|      0|    len = mg_ntohs(pkt->udp->len);  // UDP datagram length
10478|      0|    if (len < sizeof(*pkt->udp) || len > pkt->pay.len) return;  // malformed
  ------------------
  |  Branch (10478:9): [True: 0, False: 0]
  |  Branch (10478:36): [True: 0, False: 0]
  ------------------
10479|      0|    pkt->pay.len = len;  // strip excess data
10480|      0|    mkpay(pkt, pkt->udp + 1);
10481|      0|    MG_VERBOSE(("UDP %M:%hu -> %M:%hu len %u", mg_print_ip4, &pkt->ip->src,
  ------------------
  |  | 1826|      0|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10482|      0|                mg_ntohs(pkt->udp->sport), mg_print_ip4, &pkt->ip->dst,
10483|      0|                mg_ntohs(pkt->udp->dport), (int) pkt->pay.len));
10484|      0|    if (ifp->enable_dhcp_client && pkt->udp->dport == mg_htons(68) &&
  ------------------
  |  | 2094|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (10484:9): [True: 0, False: 0]
  |  Branch (10484:36): [True: 0, False: 0]
  ------------------
10485|      0|        len >= offsetof(struct dhcp, options)) {
  ------------------
  |  Branch (10485:9): [True: 0, False: 0]
  ------------------
10486|      0|      pkt->dhcp = (struct dhcp *) (pkt->udp + 1);
10487|      0|      mkpay(pkt, &pkt->dhcp->options);
10488|      0|      rx_dhcp_client(ifp, pkt);
10489|      0|    } else if (ifp->enable_dhcp_server && pkt->udp->dport == mg_htons(67) &&
  ------------------
  |  | 2094|      0|#define mg_htons(x) mg_ntohs(x)
  ------------------
  |  Branch (10489:16): [True: 0, False: 0]
  |  Branch (10489:43): [True: 0, False: 0]
  ------------------
10490|      0|               len >= offsetof(struct dhcp, options)) {
  ------------------
  |  Branch (10490:16): [True: 0, False: 0]
  ------------------
10491|      0|      pkt->dhcp = (struct dhcp *) (pkt->udp + 1);
10492|      0|      mkpay(pkt, &pkt->dhcp->options);
10493|      0|      rx_dhcp_server(ifp, pkt);
10494|      0|    } else if (!rx_udp(ifp, pkt)) {
  ------------------
  |  Branch (10494:16): [True: 0, False: 0]
  ------------------
10495|       |      // Should send ICMP Destination Unreachable for unicasts, but keep
10496|       |      // silent
10497|      0|    }
10498|      0|  } else if (pkt->ip->proto == 6) {
  ------------------
  |  Branch (10498:14): [True: 0, False: 0]
  ------------------
10499|      0|    uint8_t off;
10500|      0|    pkt->tcp = (struct tcp *) (pkt->pay.buf);
10501|      0|    if (pkt->pay.len < sizeof(*pkt->tcp)) return;
  ------------------
  |  Branch (10501:9): [True: 0, False: 0]
  ------------------
10502|      0|    off = pkt->tcp->off >> 4;  // account for opts
10503|      0|    if (off < sizeof(*pkt->tcp) / 4 || pkt->pay.len < (uint16_t) (4 * off))
  ------------------
  |  Branch (10503:9): [True: 0, False: 0]
  |  Branch (10503:40): [True: 0, False: 0]
  ------------------
10504|      0|      return;
10505|      0|    mkpay(pkt, (uint32_t *) pkt->tcp + off);
10506|      0|    MG_VERBOSE(("TCP %M:%hu -> %M:%hu len %u", mg_print_ip4, &pkt->ip->src,
  ------------------
  |  | 1826|      0|#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10507|      0|                mg_ntohs(pkt->tcp->sport), mg_print_ip4, &pkt->ip->dst,
10508|      0|                mg_ntohs(pkt->tcp->dport), (int) pkt->pay.len));
10509|      0|    rx_tcp(ifp, pkt);
10510|      0|  } else {
10511|      0|    MG_DEBUG(("Unknown IP proto %x", (int) pkt->ip->proto));
  ------------------
  |  | 1825|      0|#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
  |  |  ------------------
  |  |  |  | 1813|      0|  do {                      \
  |  |  |  | 1814|      0|    if (0) mg_log args;     \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1814:9): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  |  | 1815|      0|  } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1815:12): [Folded, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
10512|      0|    if (mg_log_level >= MG_LL_VERBOSE)
  ------------------
  |  Branch (10512:9): [True: 0, False: 0]
  ------------------
10513|      0|      mg_hexdump(pkt->ip, pkt->pay.len >= 32 ? 32 : pkt->pay.len);
  ------------------
  |  Branch (10513:27): [True: 0, False: 0]
  ------------------
10514|      0|  }
10515|      8|}
fuzz.c:_ZL5mkpayP3pktPv:
 8860|     26|static void mkpay(struct pkt *pkt, void *p) {
 8861|     26|  pkt->pay =
 8862|     26|      mg_str_n((char *) p, (size_t) (&pkt->pay.buf[pkt->pay.len] - (char *) p));
 8863|     26|}
fuzz.c:_ZL9ipcsum_okPKv:
 8883|     19|static bool ipcsum_ok(const void *d) {
 8884|     19|  struct ip *ip = (struct ip *) d;
 8885|     19|  return (ipcsum(d, (ip->ver & 0x0F) * 4) == 0);
 8886|     19|}
fuzz.c:_ZL7rx_icmpP11mg_tcpip_ifP3pkt:
 9255|      7|static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
 9256|      7|  size_t plen = pkt->pay.len;
 9257|      7|  if (!icmpcsum_ok(pkt->icmp, sizeof(struct icmp) + plen)) return;
  ------------------
  |  Branch (9257:7): [True: 6, False: 1]
  ------------------
 9258|      1|  if (pkt->icmp->type == 8 && pkt->ip != NULL && pkt->ip->dst == ifp->ip) {
  ------------------
  |  Branch (9258:7): [True: 0, False: 1]
  |  Branch (9258:31): [True: 0, False: 0]
  |  Branch (9258:50): [True: 0, False: 0]
  ------------------
 9259|      0|    size_t l2_max_overhead = ifp->framesize - ifp->l2mtu;
 9260|      0|    size_t hlen = sizeof(struct ip) + sizeof(struct icmp);
 9261|      0|    size_t room = ifp->tx.len - hlen - l2_max_overhead;
 9262|      0|    uint8_t *l2addr;
 9263|      0|    struct ip *ip;
 9264|      0|    struct icmp *icmp;
 9265|      0|    struct mg_addr ips;
 9266|      0|    ips.addr.ip4 = pkt->ip->src;
 9267|      0|    ips.is_ip6 = false;
 9268|      0|    if ((l2addr = get_return_l2addr(ifp, &ips, false, pkt)) == NULL)
  ------------------
  |  Branch (9268:9): [True: 0, False: 0]
  ------------------
 9269|      0|      return;  // safety net for lousy networks
 9270|      0|    if (plen > room) plen = room;
  ------------------
  |  Branch (9270:9): [True: 0, False: 0]
  ------------------
 9271|      0|    ip = tx_ip(ifp, l2addr, 1, 0, ifp->ip, pkt->ip->src, sizeof(*icmp) + plen);
 9272|      0|    icmp = (struct icmp *) (ip + 1);
 9273|      0|    memset(icmp, 0, sizeof(*icmp));        // Set csum, type, code to 0
 9274|      0|    memcpy(icmp + 1, pkt->pay.buf, plen);  // Copy RX payload to TX
 9275|      0|    icmp->csum = ipcsum(icmp, sizeof(*icmp) + plen);
 9276|      0|    driver_output(
 9277|      0|        ifp, mg_l2_trailer(ifp, hlen + plen, (uint8_t *) ip + hlen + plen));
 9278|      0|  }
 9279|      1|}
fuzz.c:_ZL11icmpcsum_okPKvm:
 8888|      7|static bool icmpcsum_ok(const void *d, size_t len) {
 8889|      7|  return (ipcsum(d, len) == 0);
 8890|      7|}

