// File: /workspace/github_cpp_makefile_star2_O2/davidgfnet[P]tadns/tadns.cc
// Function: DNSResolver::parse_udp(unsigned char const*, int)
void DNSResolver::parse_udp(const unsigned char *pkt, int len) {
    Query *q;
    struct header *header = (struct header *) pkt;

    /* Return if we did not send that query */
    if ((q = find_active_query(ntohs(header->tid))) == NULL)
        return;

    /* Actually parse the packet */
    auto dnsp = parse_udp_packet(pkt, len);

    std::vector< std::tuple<unsigned, void*, std::string, enum dns_record_type, dns_callback_t> > deferred;
    if (ntohs(header->nqueries) != 1)
        /* We sent 1 query. We want to see more that 1 answer. */
        call_user_rec(q, DNS_ERROR);
    else if ((header->nanswers | header->nauth | header->nother) == 0)
        /* Received 0 answers */
        call_user_rec(q, DNS_DOES_NOT_EXIST);
    else if (dnsp.questions.size() == 0 || dnsp.questions[0].name != q->name)
        /* Check whether the query matches at all! */
        call_user_rec(q, DNS_ERROR);
    else {
        struct cache_entry entry;
        entry.hits = 0;
        entry.expire = std::numeric_limits<time_t>::max();
        entry.replies = dnsp.answers;

        for (const auto &e: dnsp.answers)
            entry.expire = std::min(time(NULL) + (time_t)e.ttl, entry.expire);

        // Detected some 0 TTL answers, that's an issue cause we rely on the cache as an intermediate
        // structure. That works as long as ttls are significantly bigger than DNS response latency
        entry.expire = std::max(time(NULL) + MIN_TTL_TIME, entry.expire);

        // Insert finding in the cache
        auto cacheentry = std::make_pair(q->name, q->qtype);
        cached.erase(cacheentry);
        auto res = cached.emplace(cacheentry, entry);

        /* If query has a dependant, do not notify the user but re-schedule it */
        if (q->deps.size())
            for (auto de: q->deps)
                deferred.push_back(std::make_tuple(q->niter, de->ctx, de->name, (enum dns_record_type)de->qtype, de->callback));
        else
            call_user(this, q->name, q->qtype, &res.first->second, q->callback, q->ctx, DNS_OK);
    }

    // Delete from active queries and cleanup
    active.erase(dnsp.header.tid);
    ongoing.erase(std::make_pair(q->name, q->qtype));
    assert(active.size() == ongoing.size());

    // Remove the query from the deps list
    delete q;

    // Retry deferred queries
    for (auto df: deferred)
        resolveInt(std::get<0>(df), std::get<1>(df), std::get<2>(df), std::get<3>(df), std::get<4>(df));

    purgeCache();
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x148, %rsp            # imm = 0x148
movl %edx, %ebp
movq %rsi, %r15
movq %rdi, %r13
movzwl (%rsi), %eax
rolw $0x8, %ax
movzwl %ax, %esi
callq 0x6080
testq %rax, %rax
je 0x46dc
movq %rax, %r14
leaq 0xa0(%rsp), %rdi
movq %r15, %rsi
movl %ebp, %edx
callq 0x8cf2
xorps %xmm0, %xmm0
andq $0x0, 0x20(%rsp)
movaps %xmm0, 0x10(%rsp)
pushq $0x3
popq %rbp
cmpw $0x100, 0x4(%r15)       # imm = 0x100
movq %r14, 0x8(%rsp)
jne 0x45dd
movzwl 0x8(%r15), %eax
orw 0x6(%r15), %ax
orw 0xa(%r15), %ax
je 0x45da
movq 0xb0(%rsp), %rdi
cmpq %rdi, 0xb8(%rsp)
je 0x45dd
addq $0x8, %rdi
leaq 0x10(%r14), %r15
movq %r15, %rsi
callq 0x60be
testb %al, %al
jne 0x45dd
xorps %xmm0, %xmm0
leaq 0x70(%rsp), %rdi
andq $0x0, 0x10(%rdi)
movaps %xmm0, (%rdi)
andl $0x0, 0x20(%rdi)
movabsq $0x7fffffffffffffff, %rax # imm = 0x7FFFFFFFFFFFFFFF
movq %rax, 0x18(%rdi)
leaq 0xc8(%rsp), %rsi
callq 0x393c
movq 0xc8(%rsp), %rbx
movq 0xd0(%rsp), %r12
xorl %edi, %edi
callq 0x3260
cmpq %r12, %rbx
je 0x46ee
movl 0x48(%rbx), %ecx
addq %rcx, %rax
movq 0x88(%rsp), %rcx
cmpq %rax, %rcx
cmovlq %rcx, %rax
movq %rax, 0x88(%rsp)
addq $0x50, %rbx
jmp 0x45a7
pushq $0x1
popq %rbp
movq %r13, %rdi
movq %r14, %rsi
movl %ebp, %edx
callq 0x48e0
leaq 0x38(%r13), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x71a6
leaq 0x10(%r14), %rsi
addq $0xc, %r14
leaq 0x30(%rsp), %rdi
movq %r14, %rdx
callq 0x67e0
leaq 0x70(%r13), %rdi
leaq 0x30(%rsp), %rsi
callq 0x6fa4
leaq 0x30(%rsp), %rdi
callq 0x3140
movq 0x50(%r13), %rax
cmpq 0x98(%r13), %rax
jne 0x482d
movq %r13, %r14
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0x5fb4
pushq $0x78
popq %rsi
movq %rbx, %rdi
callq 0x32b0
movq 0x10(%rsp), %r15
movq 0x18(%rsp), %r12
leaq 0x128(%rsp), %r13
cmpq %r12, %r15
je 0x46c0
leaq 0x30(%rsp), %rdi
movq %r15, %rsi
callq 0x6bd8
movl 0x68(%rsp), %ebp
movq 0x60(%rsp), %rbx
movq %r13, %rdi
leaq 0x40(%rsp), %rsi
callq 0x3360
movl 0x38(%rsp), %r8d
movq 0x30(%rsp), %r9
movq %r14, %rdi
movl %ebp, %esi
movq %rbx, %rdx
movq %r13, %rcx
callq 0x49f4
movq %r13, %rdi
callq 0x3140
leaq 0x40(%rsp), %rdi
callq 0x3140
addq $0x40, %r15
jmp 0x4666
callq 0x448c
leaq 0x10(%rsp), %rdi
callq 0x60c8
leaq 0xa0(%rsp), %rdi
callq 0x3a46
addq $0x148, %rsp            # imm = 0x148
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
addq $0x3c, %rax
movq 0x88(%rsp), %rcx
cmpq %rcx, %rax
cmovleq %rcx, %rax
movq %rax, 0x88(%rsp)
leaq 0xc(%r14), %rdx
leaq 0x100(%rsp), %rdi
movq %r15, %rsi
callq 0x67e0
leaq 0xa0(%r13), %rbx
leaq 0x100(%rsp), %rsi
movq %rbx, %rdi
callq 0x72f0
leaq 0x100(%rsp), %rsi
leaq 0x70(%rsp), %rdx
movq %rbx, %rdi
callq 0x74f0
cmpq $0x0, 0x68(%r14)
je 0x47c0
movq %r14, %rax
movq %r13, %r14
movq 0x58(%rax), %r13
leaq 0x48(%rax), %rbx
leaq 0x8(%rax), %r12
leaq 0x30(%rsp), %rbp
leaq 0x10(%rsp), %r15
cmpq %rbx, %r13
je 0x4809
movq 0x20(%r13), %r9
leaq 0x30(%r9), %rdx
leaq 0x10(%r9), %rcx
movzwl 0xc(%r9), %eax
movl %eax, 0x4(%rsp)
addq $0x38, %r9
movq %rbp, %rdi
movq %r12, %rsi
leaq 0x4(%rsp), %r8
callq 0x6b72
movq %r15, %rdi
movq %rbp, %rsi
callq 0x7774
leaq 0x40(%rsp), %rdi
callq 0x3140
movq %r13, %rdi
callq 0x32e0
movq %rax, %r13
jmp 0x476c
movq %rax, %r12
leaq 0xe0(%rsp), %rdi
movq %r15, %rsi
callq 0x3360
movq %r14, %rax
movq %r13, %r14
movzwl 0xc(%rax), %esi
addq $0x48, %r12
movq 0x30(%rax), %r8
movq 0x38(%rax), %rcx
leaq 0xe0(%rsp), %rdi
movq %r12, %rdx
xorl %r9d, %r9d
callq 0x4970
leaq 0xe0(%rsp), %rdi
callq 0x3140
leaq 0x100(%rsp), %rdi
callq 0x3140
leaq 0x70(%rsp), %rdi
callq 0x3a60
movq %r14, %r13
movq 0x8(%rsp), %r14
jmp 0x45ea
leaq 0x5854(%rip), %rdi      # 0xa088
leaq 0x586d(%rip), %rsi      # 0xa0a8
leaq 0x589e(%rip), %rcx      # 0xa0e0
movl $0x186, %edx            # imm = 0x186
callq 0x31c0
movq %rax, %rbx
leaq 0xe0(%rsp), %rdi
jmp 0x487d
jmp 0x4870
jmp 0x485d
movq %rax, %rbx
jmp 0x488f
jmp 0x4870
movq %rax, %rbx
leaq 0x30(%rsp), %rdi
jmp 0x48bc
jmp 0x489d
movq %rax, %rbx
jmp 0x4882
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x3140
leaq 0x100(%rsp), %rdi
callq 0x3140
leaq 0x70(%rsp), %rdi
callq 0x3a60
jmp 0x48c1
jmp 0x489d
movq %rax, %rbx
jmp 0x48c1
movq %rax, %rbx
jmp 0x48b7
movq %rax, %rbx
leaq 0x128(%rsp), %rdi
callq 0x3140
leaq 0x40(%rsp), %rdi
callq 0x3140
leaq 0x10(%rsp), %rdi
callq 0x60c8
leaq 0xa0(%rsp), %rdi
callq 0x3a46
movq %rbx, %rdi
callq 0x33f0